diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..295a47844 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,67 @@ +# Use the specified image as the base +FROM mcr.microsoft.com/devcontainers/base:bullseye + +# Set environment variables, if any +# ENV MY_ENV_VAR=my_value + +# Run package updates and install packages +RUN apt-get update + + +CMD code --install-extension ms-mssql.mssql + +USER vscode +RUN curl https://run.spawn.cc/install | sh +ENV PATH="/home/vscode/.spawnctl/bin:$PATH" + +USER root +RUN apt-get update && apt-get install -y curl gnupg software-properties-common \ + && curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ + && chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list \ + && apt-get update \ + && apt-get install -y gh + +RUN apt-get update && \ + apt-get install -y mono-complete + +ENV TSQLTCERTPATH /var/tSQLtCertTemp +ENV TSQLTCERTPASSWORD P@ssw0rdP@ssw0rdP@ssw0rdP@ssw0rd +RUN mkdir -p $TSQLTCERTPATH && \ + chmod 777 $TSQLTCERTPATH + +# Add the Microsoft SQL Server repository +RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \ + && curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/msprod.list + +RUN apt-get update +ENV ACCEPT_EULA=Y +RUN apt-get install -y mssql-tools unixodbc-dev +ENV PATH="$PATH:/opt/mssql-tools/bin" + +RUN apt-get install -y unzip + +RUN curl -L https://aka.ms/sqlpackage-linux -o sqlpackage.zip \ + && unzip sqlpackage.zip -d /opt/sqlpackage \ + && chmod +x /opt/sqlpackage/sqlpackage \ + && rm sqlpackage.zip +ENV PATH="$PATH:/opt/sqlpackage" + +RUN apt-get install -y wget apt-transport-https software-properties-common && \ + wget -q "https://packages.microsoft.com/config/debian/$(. /etc/os-release && echo $VERSION_ID)/packages-microsoft-prod.deb" -O packages-microsoft-prod.deb && \ + dpkg -i packages-microsoft-prod.deb && \ + apt-get update && \ + apt-get install -y powershell + +RUN pwsh -Command "Install-Module -Name SqlServer -Scope AllUsers -AllowClobber -Force" + +RUN pwsh -Command "Install-Module -Name Az -AllowClobber -Scope AllUsers -Force" +RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash +RUN curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64 \ + && chmod +x ./bicep \ + && mv ./bicep /usr/local/bin/bicep + +# Set the default shell to PowerShell +SHELL ["pwsh", "-Command"] + + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..5f4b1512b --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,69 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-in-docker +{ + "name": "Docker in Docker", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + //"image": "mcr.microsoft.com/devcontainers/base:bullseye", + //"image": "mcr.microsoft.com/mssql/server:2022-latest", + // "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "build": { + // Path is relataive to the devcontainer.json file. + "dockerfile": "Dockerfile" + }, + + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "enableNonRootDocker": "true", + "moby": "true" + }, + // "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, + "ghcr.io/devcontainers/features/dotnet:1": {}, + "ghcr.io/devcontainers/features/git:1": {}, + // "ghcr.io/devcontainers/features/git-lfs:1": {}, + // "ghcr.io/devcontainers/features/github-cli:1": {}, + // "ghcr.io/devcontainers/features/go:1": {}, + // "ghcr.io/devcontainers/features/powershell:1": {}, + // "ghcr.io/devcontainers/features/python:1": {}, + }, + + // Use this environment variable if you need to bind mount your local source code into a new container. + "remoteEnv": { + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [], + + "customizations": { + "vscode": { + "settings": { + "remote.autoForwardPorts": false + }, + "extensions": [ + "ms-mssql.mssql", + "redhat.vscode-yaml", + "ms-vscode.powershell", + "ms-azuretools.vscode-docker", + "ms-mssql.sql-bindings-vscode", + "ms-mssql.sql-database-projects-vscode", + "ms-mssql.data-workspace-vscode", + "github.vscode-github-actions", + "ms-dotnettools.csdevkit", + "ms-vscode.powershell", + "ms-azuretools.vscode-bicep", + ] + } + }, + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": ["/bin/sh", "-c", "whoami && pwd && chmod 777 ./.devcontainer/postCreateCommand.sh && ./.devcontainer/postCreateCommand.sh"], // + + // Use 'postStartCommand' to run commands after the container is created. + "postStartCommand": ["/bin/sh", "-c", "whoami && pwd && chmod 777 ./.devcontainer/postStartCommand.sh && ./.devcontainer/postStartCommand.sh"], // + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} + + diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh new file mode 100755 index 000000000..27d92af5e --- /dev/null +++ b/.devcontainer/postCreateCommand.sh @@ -0,0 +1,11 @@ +cd "$(dirname "$0")" + +docker --version +docker-compose -f sqlserver.yml up -d --force-recreate + +cd "$TSQLTCERTPATH" +openssl req -x509 -newkey rsa:4096 -keyout tSQLtOfficialSigningKey.key -out tSQLtOfficialSigningKey.crt -days 365 -nodes -subj "/CN=yourdomain.com" +openssl pkcs12 -export -out tSQLtOfficialSigningKey.pfx -inkey tSQLtOfficialSigningKey.key -in tSQLtOfficialSigningKey.crt -passout pass:"$TSQLTCERTPASSWORD" + + +# pwsh -File ../tSQLt/PrepareServer.ps1 \ No newline at end of file diff --git a/.devcontainer/postStartCommand.sh b/.devcontainer/postStartCommand.sh new file mode 100755 index 000000000..b505c56de --- /dev/null +++ b/.devcontainer/postStartCommand.sh @@ -0,0 +1,4 @@ +cd "$(dirname "$0")" + +docker --version +docker-compose -f sqlserver.yml up -d \ No newline at end of file diff --git a/.devcontainer/sqlserver.yml b/.devcontainer/sqlserver.yml new file mode 100644 index 000000000..f11f3d9ed --- /dev/null +++ b/.devcontainer/sqlserver.yml @@ -0,0 +1,9 @@ +version: "3" +services: + sql_server: + image: mcr.microsoft.com/mssql/server:2022-latest + ports: + - "1433:1433" + environment: + ACCEPT_EULA: 'Y' + MSSQL_SA_PASSWORD: 'P@ssw0rd' diff --git a/.devcontainer/tSQLtOfficialSigningKey.crt b/.devcontainer/tSQLtOfficialSigningKey.crt new file mode 100644 index 000000000..ea7d777b9 --- /dev/null +++ b/.devcontainer/tSQLtOfficialSigningKey.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFEzCCAvugAwIBAgIUA+19JzEdOm4/g23a0HCbrZuMPGMwDQYJKoZIhvcNAQEL +BQAwGTEXMBUGA1UEAwwOeW91cmRvbWFpbi5jb20wHhcNMjMxMjAxMjAxMzA5WhcN +MjQxMTMwMjAxMzA5WjAZMRcwFQYDVQQDDA55b3VyZG9tYWluLmNvbTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAOss5YSKp/ARdrfH7M20JT6y8KvX0iIj +26oMM/JgeAvzNHt7CRnneVtJQpQTpfT0ugskolBV/XHGJ+3bOdnTsDiWea6dZ7zq +SOIB0T3R+dA3EDFNUaVysVvrKzLU/GZL9RsZpMyvNUoChcL7UyTp+RWvS0reFCtp +wpoLsrE0YCFckoDCFiKFivdLg/eESJyeR6W3fq+8XrlqZ2Vin+FbukH/eTC3aoUO +s9z25K6v8nDn4EwqgDGdPyyU4EqnFy5oxEWwd1YoGQjXbGXTVZ6L8nUySadr8yXh +DAc2Orsd0RN5r6vJJFDbxbab0mYayyq7ZfoGjKVbgUS2jZHMpDUhgnTjXD+oI7PV +TrIqnY0pRTzh8xVOgFQP8H5J9aIS/tZDvImItmZ9MR1w/PoXt4VHd7nR8NMG/68I +f9CXSj3Fza+bCw3az+PTd04BC14kxXMPfRahu2KB4TZJBOQeTRJaB0aq8Lo1hZE0 +R6Amds3ouMo0jRww1LJ2r7CLRRp0CXRn+xD3e1GjcFQrW4vKTjR+7fSzJmpbl0Gf +XvicJBxLUSx6fIr1eEzEIy5zeZi2gK+SZ8zwIoN1xLKnED2WY2fYupuuw1CsG+vP +61087mJc1WCZGaTP2iQgfp7/P+WApzbM4Rvtbem1K9Jtq/F+EHHVJOZXqs50/+Lu +cz8DgvBWV5sxAgMBAAGjUzBRMB0GA1UdDgQWBBTSgnxtHjMiZWC78QZOjshCcwjh +XTAfBgNVHSMEGDAWgBTSgnxtHjMiZWC78QZOjshCcwjhXTAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCLpIQhtjlyu1J4tVASpA4BhCVbjibDYZQF +xJ2Bbpkk/LcspV3Ekgij1aQBQNwoEPbU3uxog+xJr8hWuN5GmU2btCToeG2C7OKA +Zn7USHuPoFUV8FA1MAS4iFrQOnZykzgX611lyeE7/ooABwidPZoVcvoWb5U6Niel +PqDUoUrMg3gRIaG9zm4+009TDbcntfS/MtX6wrMKXlke01PQtLo3ohmti1KURXqI +7Hu9NouFGxsUT+o8bkip/CsbScc7Ief9ADAJGEw+TSu2mD+1f7zgPeNzrR0kKbxp +0Kr3OXUCophzWaO+oIEYzZMLXUpA9jVW5NUPcmW+shuT0IiK3WQJnpMBaGzs9XQT +8LtrJrD9uVq9HpAGnjTfzoMWpBkqeIaG772NDKq9Z8LG4JVo2gV9rGC9uysDcms0 +dGFt5AfFecM5nOqsPss4BjP85ZH7quzIhm57SVaMvuO3N2OvHyoJJDy4OQy7P/rq +fBrmjP//Jb/i/hcRdZt17LhRdU2tuESHNWReFn0wRNLXOjkgg+Nntfl7qOUfNC23 +///3xTr5UhfArr2HZn9uo7VrrF99mF4CJTmqwic1e5RC3knnNwwB7JR8/O0H5csL +qKy57PSAU+w0pCrw/a4qeX+IswRLvQ6myTKIiDDGAruN/HOYEsAW3kuSLOxYFMKh +9F7w2nGAcA== +-----END CERTIFICATE----- diff --git a/.devcontainer/tSQLtOfficialSigningKey.key b/.devcontainer/tSQLtOfficialSigningKey.key new file mode 100644 index 000000000..6adb524f8 --- /dev/null +++ b/.devcontainer/tSQLtOfficialSigningKey.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDrLOWEiqfwEXa3 +x+zNtCU+svCr19IiI9uqDDPyYHgL8zR7ewkZ53lbSUKUE6X09LoLJKJQVf1xxift +2znZ07A4lnmunWe86kjiAdE90fnQNxAxTVGlcrFb6ysy1PxmS/UbGaTMrzVKAoXC ++1Mk6fkVr0tK3hQracKaC7KxNGAhXJKAwhYihYr3S4P3hEicnkelt36vvF65amdl +Yp/hW7pB/3kwt2qFDrPc9uSur/Jw5+BMKoAxnT8slOBKpxcuaMRFsHdWKBkI12xl +01Wei/J1Mkmna/Ml4QwHNjq7HdETea+rySRQ28W2m9JmGssqu2X6BoylW4FEto2R +zKQ1IYJ041w/qCOz1U6yKp2NKUU84fMVToBUD/B+SfWiEv7WQ7yJiLZmfTEdcPz6 +F7eFR3e50fDTBv+vCH/Ql0o9xc2vmwsN2s/j03dOAQteJMVzD30WobtigeE2SQTk +Hk0SWgdGqvC6NYWRNEegJnbN6LjKNI0cMNSydq+wi0UadAl0Z/sQ93tRo3BUK1uL +yk40fu30syZqW5dBn174nCQcS1EsenyK9XhMxCMuc3mYtoCvkmfM8CKDdcSypxA9 +lmNn2LqbrsNQrBvrz+tdPO5iXNVgmRmkz9okIH6e/z/lgKc2zOEb7W3ptSvSbavx +fhBx1STmV6rOdP/i7nM/A4LwVlebMQIDAQABAoICAHdqfskEly4B0CSV8hqpxNfH +iQnZNyx6xMneFGqYrZxzzEx/NyneLfM6igIiz/xIYEfUPE9Kur0Q/6l5zjBbm3nA +ft05tDlrRcLtZVBc1NrzetduCW1XhdPE4FSZbeiL3VP7e4Er3oVMLpvJfniaDg8C +ydqkVd2NgHE0S3JLxBxsoz+aTh8NbHkR8Vq34x8UCBGP0VZu8jJ4YzRKFiEasMNe +dC1WlVInGxGylIBXe2X1eCF0209WJ4P9vL5rhgvcyv0QFCi9h6jDqpkx7KHrMhxs +gpXu7LJpSfBHix8EjuuyuI8kPbqJPiXxja6nIE78hVWmCbjVdBhuEgjcvuzzrQew +U9Ftq4+A5DHb1oBky86/9SHIYAFZQnZfc1izTMxdRcTPQB21hRq/88hi0fg+yk1D +eL9wcabt7PAhj205eYFgoZHYnV+Ep69natcILo2ckZqiCioLvKHk+h1AqTe8xgVf +TGPpq+s6ZBtJfvQ1ePTJBGc4/iPJ6pDJ6Ox87E9m7NYSYsvcPVxwOW0+AIQfmllE +U1bMZNCkzJHEa9BpwABUdUjTlwRuiZRQwfKbiMHmuf2tixumglqPapeXURTKXYd7 +7plP+wab/BPQw7ZG9MHTl5e4GpNsCn5okNHUijoArKLrtG5DzCGnPu1tbn2fbvPn +hIamTpp2ev0vHGRgIU+BAoIBAQD1hD5E8b111bOisQhlgox+AtT4THJIwFuOg9xh +zfcSgbi1X8P3AQaiVpjLrblS0JADDRMIsM3kPnq5ExGmhzhlVfhhkJtj2lUjPgsO +pVr+MX/PN6CVOvCis2MQJ+L6QThmEk6UtWluI7WZJDeLmd0RT+UGMLgj+4MZcptC +HY8T7L4RUb8q32DLJZ8yQ+Eqn7bzbywMCZy/i6zEm39esH1aCoNL7Nq3SOQnYzX4 +X3xvKPZQwyFfj5kN2C7taUDSwGV07AmVkJH7iibun4F+PUJiCu0PZU3DPUPCSdpv +C+LuI5u2HX8MXFe+fs1zSOMJ7Pn/n3eV3IK8H9LabcVMise5AoIBAQD1N5zwcTQM +0ubOYwwKLbbel8lVV7t9Nz8ic+jfuHuKJEpo3QUp5izFB6UUwVp3UXM23XNFnJi9 +krl4XdxnGs9x33elt6iMmwxpt12t4EqxV3kRxh1chyZjpxuFJhb5A/dNu5QHtoAx +OpDzIHqa3pEOLrxhFFkJOEHH2FMtm30NELNvFkbbw0WFvKzDgZ+/ldqtHCn1Ln3r +zScvmovNtwX1jbLZt9E2lASVLp9xUIevaJdz/qUjzuaopE1bWhiI0EWhifC9bb6c +zUgdqaUjQH3JkCVwCK4/2qt7H+d8qK2XdEDfBYEyjd0304PMh77vjf653Lw5pEUY +JNZxadLEdbs5AoIBAQDX7NRvAkRka+wuu4/s5uH0uTzgmysvvK1JK8MY6XHQfvIZ +4f2RMP/Kqmp7R3Bj2zWs2UTSMd0CTcjVGGY/lVEOHovyEqH3McAK3LgQy3C5eoMz +lXLPjCSykx4eyVWgTtfxPUyLEPmGejVuWCHZzxpT7XY4+YQZcUwdh2Pww9pf5ahL +xx9f71FLmOzn4jcXq5vVgQK2G4YWGBt8Vl2ww3ubQv+yOL8qzxqJYYHHzQK9KMNo +yBSD3OD5AhZTimwOblNMf4L2XU1mclxHJVVX1zyYyY8wKSI5AZqkNxu66jNMyVha +1Jo2Hsi0qwS5zXKP+jDsli0wSd1Y4owour340V1RAoIBAQCaBoWYbbLA/1QkfQhZ ++F7uMC8xYPsOar5IWMAEjm9i1Oq8NWAB8mdalzO09sJpQgr5gl3ecr9qDBhdp69C +QA/fOfuAZv0C3H0OhjPcfI7OF+CfLm7Q6L9PRu69UrCJV1lmRRV1Rsf8pAnZ/SOl +1XkNjIOdAtfuN5zx90o/0nPY2g2rEDYP4fbwSxPFdc0u3OTPaWpdbAeCLomXmB6K +Z5ThqVCW+qP6AT1jqzZRScEAh9Th8iguds5hTVqdr9jLTu79yZQimCVrfnH219E3 +dFHOYrFxTrKMv0CJBQA1SApJoKcCrwV5CKzUXRJjTTy8YdeHTUQZfLo9sR3VfR/7 +cOvZAoIBAGN4WxCHbWD0bpofe17oKeY9aTl5lr2qhqC1WO4vBvmI7XVlXOFShL3v +DBpQOYAa45o/85nWeF+6F2jroQymuPNcV4g9OzZCqg/XuHizM0JXaplpAnV458Ku +rZo1P3TnXBgKrLSpL7KloKICbo8aegvkj/FJNq0EqGweq/aMPZB69u9PBsMlGtIN +GviD8mvEOOQfVu+qy0gcD9x51SNH2GYVE2U9vdaxCtf+8dnU+JWsU9UC82I/HW8e +0vDyxq4CX/7TZRJsyFDZG8k/eutRIUx6+z9n7NSkGOC0tuv2MAkKZUYd+wXS1WTI +11bvPI4fB5GVVMDLhPFgNyqPTwE4oJg= +-----END PRIVATE KEY----- diff --git a/.devcontainer/tSQLtOfficialSigningKey.pfx b/.devcontainer/tSQLtOfficialSigningKey.pfx new file mode 100644 index 000000000..ac63dd1e0 Binary files /dev/null and b/.devcontainer/tSQLtOfficialSigningKey.pfx differ diff --git a/Build/Build.ps1 b/Build/Build.ps1 deleted file mode 100644 index f47d0d53c..000000000 --- a/Build/Build.ps1 +++ /dev/null @@ -1,59 +0,0 @@ -Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $CommitId -); - -$scriptPath = $MyInvocation.MyCommand.Path; -$invocationDir = Split-Path $scriptPath; -$buildPath = $invocationDir +'/'; -$tempPath = $invocationDir + '/temp/tSQLtBuild/'; -$outputPath = $invocationDir + '/output/tSQLtBuild/'; -$sourcePath = $invocationDir + '/../Source/'; -$testUtilPath = $invocationDir + '/../TestUtil/'; - -.($buildPath+"CommonFunctionsAndMethods.ps1"); - -Log-Output '<#--=======================================================================-->' -Log-Output '' -Log-Output '<#--=======================================================================-->' - -Set-Content -Path "temp/tSQLtBuild/CommitId.txt" -Value $CommitId; - -Log-Output '<#--=======================================================================-->' -Log-Output '' -Log-Output '<#--=======================================================================-->' - -$templateContent = Get-Content -path ($buildPath + "GetFriendlySQLServerVersion.template.sql"); -$sqlFile1Content = Get-Content -path ($sourcePath + "tSQLt.FriendlySQLServerVersion.sfn.sql"); -$sqlFile2Content = Get-Content -path ($sourcePath + "tSQLt.Private_SplitSqlVersion.sfn.sql"); - -$snip1Content = (Get-SnipContent $sqlFile1Content "/*StartSnip*/" "/*EndSnip*/"); -$snip2Content = (Get-SnipContent $sqlFile2Content "/*StartSnip*/" "/*EndSnip*/"); - -$FinalContent = (($templateContent.Replace("/*snip1content*/",$snip1Content).Replace("/*snip2content*/",$snip2Content)) -join [System.Environment]::NewLine); -Set-Content -Path ($tempPath + 'GetFriendlySQLServerVersion.sql') -Value $FinalContent; - -Log-Output '<#--=======================================================================-->' -Log-Output '' -Log-Output '<#--=======================================================================-->' - -$testUtilContent = Get-Content -path ($testUtilPath + "tSQLt_testutil.class.sql"); -$CreateBuildLogRaw = (Get-SnipContent $testUtilContent "/*CreateBuildLogStart*/" "/*CreateBuildLogEnd*/"); -$CreateBuildLog = ($CreateBuildLogRaw -join [System.Environment]::NewLine).Replace("tSQLt_testutil.CreateBuildLog","#CreateBuildLog"); -$CreateBuildLog = ($CreateBuildLog + [System.Environment]::NewLine + "EXEC #CreateBuildLog @TableName='"+'$(BuildLogTableName)'+"';" + [System.Environment]::NewLine); -Set-Content -Path ($tempPath + 'CreateBuildLog.sql') -Value ($CreateBuildLog); - -Log-Output '<#--=======================================================================-->' -Log-Output '' -Log-Output '<#--=======================================================================-->' - -$toBeZipped = @("ReleaseNotes.txt", "License.txt", "tSQLt.class.sql", "Example.sql", "PrepareServer.sql"); -$compress = @{ - CompressionLevel = "Optimal" - DestinationPath = ($outputPath + "tSQLtFiles.zip") - } -Get-ChildItem -Path ($tempPath + "*") -Include $toBeZipped | Compress-Archive @compress - -$toBeCopied = @("Version.txt", "tSQLt.class.sql", "CommitId.txt", "GetFriendlySQLServerVersion.sql", "CreateBuildLog.sql"); -Get-ChildItem -Path ($tempPath + "*") -Include $toBeCopied | Copy-Item -Destination $outputPath; -Copy-Item ($tempPath + "ReleaseNotes.txt") -Destination ($outputPath + "ReadMe.txt"); - diff --git a/Build/Build.ssmssqlproj b/Build/Build.ssmssqlproj deleted file mode 100644 index 02724cb72..000000000 --- a/Build/Build.ssmssqlproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - - - - - - - - - ChangeDbAndExecuteStatement(tSQLt.Build).sql - - - - - - CreateBuildDb.sql - - - - - - Drop(master.tSQLt_testutil).sql - - - - - - Drop(tSQLtAssemblyKey)(Pre2017).sql - - - - - - EnableExternalAccess.sql - - - - - - ExecuteAs(tSQLt.Build.SA).sql - - - - - - ExecuteAs(tSQLt.Build).sql - - - - - - ExecuteResetValidationServer.sql - - - - - - GetFailedTestCount.sql - - - - - - GetFriendlySQLServerVersion.template.sql - - - - - - GetSQLServerVersion.sql - - - - - - GetTestResults.sql - - - - - - CreateLogin(tSQLt.Build).sql - - - - - - GrantBuildPermissions.sql - - - - - - Install(master.tSQLt_testutil).sql - - - - - - Install(tSQLtAssemblyKey).sql - - - - - - PrintVersionInfo.sql - - - - - - - - - - Build.ps1 - - - - - - BuildHelper.exe - - - - - - BuildTestResultsZip.ps1 - - - - - - BuildtSQLtDacpac.ps1 - - - - - - BuildtSQLtZip.ps1 - - - - - - ChangeSigningKey_ReadMe.txt - - - - - - CommonFunctionsAndMethods.ps1 - - - - - - CreateAssemblyGenerator.exe - - - - - - CreateDebugSSMSProject.ps1 - - - - - - DacpacDeploy.ps1 - - - - - - FacadeBuildDacpac.ps1 - - - - - - FacadeBuildScript.ps1 - - - - - - FacadeValidate.ps1 - - - - - - Import-PfxCert.ps1 - - - - - - Install the tSQLt build.docx - - - - - - License.txt - - - - - - LocalBuild.bat - - - - - - LocalValidateBuild.bat - - - - - - NewRelease.doc - - - - - - ReleaseNotes.txt - - - - - - Setup.bat - - - - - - SetupDacpacBuild.ps1 - - - - - - SnInstallPfx.exe - - - - - - SourceForgePrivateKey.ppk - - - - - - tSQLt.build.xml - - - - - - tSQLt.buildCLR.xml - - - - - - tSQLt.copybuild.xml - - - - - - tSQLt.experiments.build.xml - - - - - - tSQLt.validatebuild.xml - - - - - - Version.txt - - - - - - VersionInfo.vbs - - - - - - buildNotes.txt - - - - - - buildtranslate.txt - - - - - \ No newline at end of file diff --git a/Build/BuildHelper.exe b/Build/BuildHelper.exe deleted file mode 100644 index 7c99e77b1..000000000 Binary files a/Build/BuildHelper.exe and /dev/null differ diff --git a/Build/BuildTestResultsZip.ps1 b/Build/BuildTestResultsZip.ps1 deleted file mode 100644 index cabc9385a..000000000 --- a/Build/BuildTestResultsZip.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ResultFiles -); - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; - -.($dir+"\CommonFunctionsAndMethods.ps1"); - -$OutputPath = $dir + "/output/Validate/"; -$TempPath = $dir + "/temp/Validate/"; -$TestResultsZipPath = $OutputPath + "TestResults.zip"; -$ExpectedTestResultFileNames = $ResultFiles.Split(';'); - -$ActualTestResultFiles = Get-ChildItem -Path $TempPath -Include "TestResults*.xml" -Recurse; - -if ($null -eq $ActualTestResultFiles) { - throw "ActualTestResultsFiles is null." -} -$ActualTestResultFileNames = $ActualTestResultFiles.Name; - -$compare = Compare-Object -ReferenceObject $ExpectedTestResultFileNames -DifferenceObject $ActualTestResultFileNames -PassThru; - -if ($compare.length -ne 0) { - $throwMessage = @" -Expected files: $ExpectedTestResultFileNames - -Actual files: $ActualTestResultFileNames - -Unexpected or missing files: $compare - -"@; - $throwMessage; - throw "There were missing or unexpected files." -} - -$compress = @{ - CompressionLevel = "Optimal" - DestinationPath = $TestResultsZipPath -} -Get-ChildItem -Path ($TempPath + "TestResults*.xml") -Recurse | Compress-Archive @compress diff --git a/Build/BuildtSQLtDacpac.ps1 b/Build/BuildtSQLtDacpac.ps1 deleted file mode 100644 index af109371d..000000000 --- a/Build/BuildtSQLtDacpac.ps1 +++ /dev/null @@ -1,44 +0,0 @@ -Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlPackagePath -); -<# -Technically this should be called by a matrixed job, so that dacpacs are built for all versions (we support, like not 2005, 2008) -#> - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; - -.($dir+"\CommonFunctionsAndMethods.ps1"); - -$OutputPath = $dir + "/output/DacpacBuild/"; -$TempPath = $dir + "/temp/DacpacBuild/"; - -$ServerNameTrimmed = $ServerName.Trim(); -$LoginTrimmed = $Login.Trim("'").Trim(); - - -Log-Output "FileLocation: $dir"; -Push-Location; -Set-Location $TempPath; - -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath -FileNames @("ResetValidationServer.sql","PrepareServer.sql"); -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath -FileNames ($dir+"/CreateBuildDb.sql") -Database "tempdb" -AdditionalParameters ('-v NewDbName="'+$DatabaseName+'"'); -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath -FileNames "tSQLt.class.sql" -Database "$DatabaseName"; - -$FriendlySQLServerVersion = Get-FriendlySQLServerVersion -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath; -$tSQLtDacpacFileName = "tSQLt."+$FriendlySQLServerVersion+".dacpac"; -$tSQLtApplicationName = "tSQLt."+$FriendlySQLServerVersion; -$tSQLtConnectionString = Get-SqlConnectionString -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -DatabaseName $DatabaseName; - -& "$SqlPackagePath\sqlpackage.exe" /a:Extract /scs:"$tSQLtConnectionString" /tf:"$tSQLtDacpacFileName" /p:DacApplicationName="$tSQLtApplicationName" /p:IgnoreExtendedProperties=true /p:DacMajorVersion=0 /p:DacMinorVersion=1 /p:ExtractUsageProperties=false -if($LASTEXITCODE -ne 0) { - throw "error during execution of dacpac " + $tSQLtDacpacFileName; -} - -Copy-Item -Path $tSQLtDacpacFileName -Destination $OutputPath; - -Pop-Location; diff --git a/Build/BuildtSQLtZip.ps1 b/Build/BuildtSQLtZip.ps1 deleted file mode 100644 index bdd6c1ce0..000000000 --- a/Build/BuildtSQLtZip.ps1 +++ /dev/null @@ -1,56 +0,0 @@ - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; - -.($dir+"\CommonFunctionsAndMethods.ps1"); - -$OutputPath = $dir + "/output/tSQLt/"; -$TempPath = $dir + "/temp/tSQLt/"; -$PublicOutputPath = $OutputPath + "public/"; -$PublicTempPath = $TempPath + "public/"; -$ValidationOutputPath = $OutputPath + "validation/"; -$FacadeDacpacPath = $PublicTempPath + "/FacadeDacpacs/"; -$tSQLtDacpacPath = $PublicTempPath + "/tSQLtDacpacs/"; -$tSQLtFilesZipPath = $dir + "/output/tSQLtBuild/tSQLtFiles.zip"; -$PublicOutputFiles = @( - ($dir + "/output/tSQLtBuild/ReadMe.txt"), - ($dir + "/output/tSQLtBuild/tSQLtSnippets(SQLPrompt).zip") -); -$ValidationOutputFiles = @( - ($dir + "/output/tSQLtBuild/Version.txt"), - ($dir + "/output/tSQLtBuild/CommitId.txt"), - ($dir + "/output/tSQLtBuild/tSQLt.tests.zip"), - ($dir + "/output/tSQLtBuild/tSQLtFacade.zip"), - ($dir + "/output/tSQLtBuild/CreateBuildLog.sql"), - ($dir + "/output/tSQLtBuild/GetFriendlySQLServerVersion.sql") -); - -<# Clean #> -Remove-DirectoryQuietly -Path $TempPath; -Remove-DirectoryQuietly -Path $OutputPath; - -<# Init directories, capturing the return values in a variable so that they don't print. #> -$eatPublicOutputDir = New-Item -ItemType "directory" -Path $PublicOutputPath; -$eatFacadeDacpacsDir = New-Item -ItemType "directory" -Path $FacadeDacpacPath; -$eattSQLtDacpacsDir = New-Item -ItemType "directory" -Path $tSQLtDacpacPath; -$eatValidationOutputDir = New-Item -ItemType "directory" -Path $ValidationOutputPath; - -<# Copy files to temp path #> -Expand-Archive -Path ($tSQLtFilesZipPath) -DestinationPath $PublicTempPath; -Get-ChildItem -Path ($dir + "/output/DacpacBuild/tSQLtFacade.*.dacpac") | Copy-Item -Destination $FacadeDacpacPath; -Get-ChildItem -Path ($dir + "/output/DacpacBuild/tSQLt.*.dacpac") | Copy-Item -Destination $tSQLtDacpacPath; - -<# Create the tSQLt.zip in the public output path #> -$compress = @{ - CompressionLevel = "Optimal" - DestinationPath = $PublicOutputPath + "/tSQLt.zip" -} -Get-ChildItem -Path $PublicTempPath | Compress-Archive @compress - -<# Copy all public files into public output path #> -Copy-Item -Path $PublicOutputFiles -Destination $PublicOutputPath - -<# Copy all validation files into validation output path #> -Copy-Item -Path $ValidationOutputFiles -Destination $ValidationOutputPath - - diff --git a/Build/CommonFunctionsAndMethods.ps1 b/Build/CommonFunctionsAndMethods.ps1 deleted file mode 100644 index 7dac71135..000000000 --- a/Build/CommonFunctionsAndMethods.ps1 +++ /dev/null @@ -1,220 +0,0 @@ -$PSScriptRoot; - -$MergeHashTables = {param([HashTable]$base,[HashTable]$new);$new.GetEnumerator()|%{$base.remove($_.Key);$base += @{$_.Key=$_.Value}};$base;}; -$AddTagsToResourceGroup = -{ - param([String]$ResourceGroupName,[HashTable]$newTags); - $RG = Get-AzResourceGroup -name $ResourceGroupName; - $RG|Set-AzResourceGroup -Tags ($MergeHashTables.Invoke($RG.Tags,$newTags)[0]); -} -$GetUTCTimeStamp = {param();(Get-Date).ToUniversalTime().ToString('[yyyy-MM-ddTHH:mm:ss.fffffff UTC]');}; - - -Function Log-Output{[cmdletbinding()]Param([parameter(ValueFromPipeline)]$I);Process{Write-Host ([string]::Concat($GetUTCTimeStamp.Invoke()[0],[string]::Concat(" $I")));};}; - -Log-Output($GetUTCTimeStamp.Invoke(),"Done: Loading CommonFunctionsAndMethods"); - -Function Exec-SqlFileOrQuery -{ - [CmdletBinding()] - param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath, - [Parameter(Mandatory=$true, ParameterSetName = 'File')][ValidateNotNullOrEmpty()][string[]] $FileNames, - [Parameter(Mandatory=$false, ParameterSetName = 'File')][Parameter(Mandatory=$true, ParameterSetName = 'Query')][ValidateNotNullOrEmpty()][string] $Query, - [Parameter(Mandatory=$false)][string] $DatabaseName = "", - [Parameter(Mandatory=$false)][string] $AdditionalParameters = "" - ); - - $DatabaseSelector = ""; - if($DatabaseName -ne ""){ - $DatabaseSelector = '-d "'+$DatabaseName+'"'; - } - - $ExecutionMessage = "" - $FileNameSection = ""; - <# -i input_file[,input_file2...] #> - if (![string]::isnullorempty($FileNames)) { - $FileNameSection = '-i "'+($FileNames -Join '","')+'"'; - $ExecutionMessage = $FileNames; - } - $QuerySection = ""; - if (![string]::isnullorempty($Query)) { - $QuerySection = '-Q "' + $Query + '"'; - $ExecutionMessage += " " + $Query; - } - - - $CallSqlCmd = '&"'+$SqlCmdPath+'\sqlcmd.exe" -S "'+$ServerName+'" '+$Login+' -b -I '+$FileNameSection+' '+$QuerySection+' '+$DatabaseSelector+' '+$AdditionalParameters+';'; - $CallSqlCmd = $CallSqlCmd + ';if($LASTEXITCODE -ne 0){throw "error during execution of "+$ExecutionMessage;}'; - - Invoke-Expression $CallSqlCmd -ErrorAction Stop; -} - -Function Get-SqlConnectionString -{ - [CmdletBinding()] - param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName - ); - - $ServerNameTrimmed = $ServerName.Trim(); - $LoginTrimmed = $Login.Trim(); - - <# - ☹️ - This is so questionable, but it looks like sqlpackage cannot handle valid connection strings that use a valid server alias. - The following snippet is meant to spelunk through the registry and extract the actual server from the alias. - ☹️ - #> - $resolvedServerName = $ServerNameTrimmed; - $serverAlias = Get-Item -Path HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo -ErrorAction SilentlyContinue; - if ($null -ne $serverAlias -And $serverAlias.GetValueNames() -contains $ServerNameTrimmed) { - $aliasValue = $serverAlias.GetValue($ServerNameTrimmed) - if ($aliasValue -match "DBMSSOCN[,](.*)"){ - $resolvedServerName = $Matches[1]; - } - } - - <# When using Windows Authentication, you must use "Integrated Security=SSPI" in the SqlConnectionString. Else use "User ID=;Password=;" #> - if ($LoginTrimmed -match '((.*[-]U)|(.*[-]P))+.*'){ - $AuthenticationString = $LoginTrimmed -replace '^((\s*([-]U\s+)(?\w+)\s*)|(\s*([-]P\s+)(?\S+)\s*))+$', 'User Id=${user};Password="${password}"' - } - elseif ($LoginTrimmed -eq "-E"){ - $AuthenticationString = "Integrated Security=SSPI;"; - } - else{ - throw $LoginTrimmed + " is not supported here." - } - - $SqlConnectionString = "Data Source="+$resolvedServerName+";"+$AuthenticationString+";Connect Timeout=60;Initial Catalog="+$DatabaseName+";TrustServerCertificate=true;"; - $SqlConnectionString; -} - -function Get-FriendlySQLServerVersion { - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath - ) - $ServerNameTrimmed = $ServerName.Trim(); - $LoginTrimmed = $Login.Trim(); - - $GetFriendlySQLServerVersionFullPath = (Get-ChildItem -Path ($PSScriptRoot + '/output/*') -include "GetFriendlySQLServerVersion.sql" -Recurse | Select-Object -First 1 ).FullName; - $GetFriendlySQLServerVersionStatement = (Get-Content -Path $GetFriendlySQLServerVersionFullPath).Replace([System.Environment]::NewLine,' '); - $resultSet = Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath -Query "$GetFriendlySQLServerVersionStatement" -DatabaseName 'tempdb'; - Log-Output "Friendly SQL Server Version: $resultSet"; - $resultSet.Trim(); -} - -function Update-Archive { - param ( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $ArchiveName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String[]] $FileNamesToInclude - ) - <# Create directory to unpack compressed file #> - $ArchiveDirectory = $ArchiveName + "." + (Get-Date -Format "yyyy-MM-dd-HHmm"); - New-Item -ItemType Directory -Path ".\$ArchiveDirectory"; - - <# Unpack compressed file into newly created directory #> - Expand-Archive -LiteralPath $ArchiveName -DestinationPath $ArchiveDirectory; - - <# Rename original archive file #> - $NewArchiveName = $ArchiveName + ".original"; - Rename-Item -Path $ArchiveName -NewName $NewArchiveName; - - <# Copy new files to include into the archive directory #> - foreach ($FileName in $FileNamesToInclude) { - Copy-Item $FileName -Destination $ArchiveDirectory; - } - - <# Compress files #> - $compress = @{ - Path = $ArchiveDirectory - CompressionLevel = "Fastest" - DestinationPath = $ArchiveName - } - Compress-Archive @compress -} - -function Remove-DirectoryQuietly { - param ( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $Path - ) - if (Test-Path -Path $Path) { - Remove-Item -Path $Path -Recurse -Force - } -} - -Function Remove-ResourceGroup{ - [CmdletBinding()] - Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ResourceGroupName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $BuildId); - - Write-Output "▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-"; - Write-Output ("[{0}]Start processing delete for {1}" -f ((get-date).toString("O")), ($ResourceGroupName)); - - $MyAzResourceGroup = (Get-AzResourceGroup -name "$ResourceGroupName"); - if(("RemovalBy" -in $MyAzResourceGroup.tags.keys) -and (![string]::isnullorempty($MyAzResourceGroup.tags.RemovalBy))) { - $MyAzResourceGroup = $null; - } - if($null -ne $MyAzResourceGroup) { - $Tags = @{}; - Write-Output ("Add Tag to {0}" -f $ResourceGroupName); - $Tags = $MyAzResourceGroup.Tags; - $Tags.remove("RemovalBy"); - $Tags += @{"RemovalBy"="$BuildId"}; - $MyAzResourceGroup | Set-AzResourceGroup -Tags $Tags; - Start-Sleep 10; - Write-Output ("Confirming Tags are still in place for {0}" -f $ResourceGroupName); - $MyAzResourceGroup = $MyAzResourceGroup | Get-AZResourceGroup | Where-Object {$_.Tags.RemovalBy -eq "$BuildId"}; - $MyAzResourceGroup.Tags | Format-Table; - - if($null -ne $MyAzResourceGroup) { - Write-Output "Removing Locks" - $retrievedResourceGroupName = $MyAzResourceGroup.ResourceGroupName; - Get-AzResource -ResourceGroupName $retrievedResourceGroupName | ForEach-Object { - Get-AzResourceLock -ResourceType $_.ResourceType -ResourceName $_.Name -ResourceGroupName $_.ResourceGroupName | ForEach-Object{ - Write-Output ("{0} -> {1}" -f $_.ResourceType, $_.ResourceName); - $_ | Remove-AzResourceLock -Force - } - } - Write-Output ("Removing RG {0}" -f $retrievedResourceGroupName); - $MyAzResourceGroup | Remove-AzResourceGroup -Force; - } - else { - Write-Output ("Tags changed by another process. Resource Group {0} is no longer eligible to be deleted." -f $ResourceGroupName); - } - } - else { - Write-Output ("Processing skipped for Resource Group: {0} Build Id: {1}" -f $ResourceGroupName, $BuildId); - } - Write-Output ("[{0}]Done processing delete for {1}" -f ((get-date).toString("O")), ($ResourceGroupName)) - Write-Output "▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-"; -} - -Function Get-SnipContent { - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true,ValueFromPipeline=$true)][AllowEmptyString()][string[]]$searchArray, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $startSnipPattern, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $endSnipPattern - ) - begin { - $outputOn = $false; - }; - process { - $searchArray | ForEach-Object { - if($_ -eq $endSnipPattern) { $outputOn = $false }; - if($outputOn) { $_ }; - if($_ -eq $startSnipPattern) { $outputOn = $true }; - } - }; - end { - }; -} \ No newline at end of file diff --git a/Build/CommonFunctionsAndMethods.psm1 b/Build/CommonFunctionsAndMethods.psm1 new file mode 100644 index 000000000..63f51d5ee --- /dev/null +++ b/Build/CommonFunctionsAndMethods.psm1 @@ -0,0 +1,286 @@ +$__=$__ #quiesce warnings +$CommonFunctionsAndMethodsDir = $PSScriptRoot +Write-Verbose "Loading CommonFunctionsAndMethods.psm1 from: $PSCommandPath" +. (Join-Path $CommonFunctionsAndMethodsDir 'SQLServerConnection.ps1'); + +$MergeHashTables = {param([HashTable]$base,[HashTable]$new);$new.GetEnumerator()|%{$base.remove($_.Key);$base += @{$_.Key=$_.Value}};$base;}; +$AddTagsToResourceGroup = +{ + param([String]$ResourceGroupName,[HashTable]$newTags); + $RG = Get-AzResourceGroup -name $ResourceGroupName; + $RG|Set-AzResourceGroup -Tags ($MergeHashTables.Invoke($RG.Tags,$newTags)[0]); +} +$GetUTCTimeStamp = {param();(Get-Date).ToUniversalTime().ToString('[yyyy-MM-ddTHH:mm:ss.fffffff UTC]');}; +$SQLPrintCurrentTime = "EXEC('DECLARE @C VARCHAR(MAX)=CONVERT(VARCHAR(MAX),SYSUTCDATETIME(),127);RAISERROR(@C,0,1)WITH NOWAIT;');"; + +Function Log-Output{[cmdletbinding()]Param([parameter(ValueFromPipeline)]$I);Process{Write-Host ([string]::Concat($GetUTCTimeStamp.Invoke()[0],[string]::Concat(" $I")));};}; + +Function Invoke-SqlFile +{ + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string[]] $FileNames, + [Parameter(Mandatory=$false)][string] $DatabaseName = "tempdb", + [Parameter(Mandatory=$false)][hashtable] $AdditionalParameters = @{}, + [Parameter(Mandatory=$false)][string] $ApplicationNameSuffix = $null, + [Parameter(Mandatory=$false)][bool] $PrintSqlOutput = $false + ); + $tmpInputFile = New-TemporaryFile; + $SeparatorContent = @("","GO","") + + & "$CommonFunctionsAndMethodsDir/tSQLt_Build/ConcatenateFiles.ps1" -OutputFile $tmpInputFile -InputPath $FileNames -SeparatorContent $SeparatorContent + + $parameters = @{ + ConnectionString = ($SqlServerConnection.GetConnectionString($DatabaseName,$ApplicationNameSuffix)) + InputFile = $tmpInputFile + Variable = $AdditionalParameters + } + if($PrintSqlOutput){ + $parameters['Verbose'] = $true + } + + $dddbefore = Get-Date;Write-Verbose("------->>BEFORE<<-------(CommonFunctionsAndMethods.p1:Invoke-SqlFile:Invoke-SqlCommand[$($dddbefore|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + $results = (Invoke-SqlCmd @parameters) + $dddafter = Get-Date;Write-Verbose("------->>After<<-------(CommonFunctionsAndMethods.p1:Invoke-SqlFile:Invoke-SqlCommand[$($dddafter|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + Write-Verbose("Runtime in Milliseconds: $(($dddafter-$dddbefore).TotalMilliseconds)") + return $results +} + +Function Invoke-SQLFileOrQuery +{ + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $HelperSQLPath, + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $DatabaseName = 'tempdb', + [Parameter(Mandatory=$true, ParameterSetName="Elevated")] + [switch]$Elevated, + [Parameter(Mandatory=$true, ParameterSetName="Caller")] + [switch]$Caller, + [Parameter(Mandatory=$false, ParameterSetName="Basic")] + [switch]$Basic, + [Parameter(Mandatory=$false)][string] $OutputFile = $null, + [Parameter(Mandatory=$false)][string] $Query = "", + [Parameter(Mandatory=$false)][string[]] $Files = @(), + [Parameter(Mandatory=$false)][hashtable] $AdditionalParameters = @{}, + [Parameter(Mandatory=$false)][bool] $PrintSqlOutput = $false + ); + $tempFile = $null; + + # Write-Warning("------->>NOTE<<-------(tSQLt_Validate.ps1:Invoke-SQLFileOrQuery:Adding Timestamps to Query") + # $Query = 'PRINT CONVERT(VARCHAR(MAX),SYSUTCDATETIME(),127);'+$Query+'PRINT CONVERT(VARCHAR(MAX),SYSUTCDATETIME(),127);' + + try{ + @{ + BuildLogTableName=$LogTableName + DbName = "tempdb" + ExecuteStatement=";" + NewDbName = ("[This Shouldn't be here "+(New-Guid)+']') + }.GetEnumerator()|ForEach-Object{if(!$AdditionalParameters.Contains($_.key)){$AdditionalParameters[$_.key]=$_.value;}} + + [string[]]$FileNames = @(); + if($Elevated){ + $FileNames += (Join-Path $HelperSQLPath "temp_executeas_sa.sql"|Resolve-Path) + }elseif($Caller){ + $FileNames += (Join-Path $HelperSQLPath "temp_executeas_caller.sql"|Resolve-Path) + }else{ + $FileNames += (Join-Path $HelperSQLPath "temp_executeas.sql"|Resolve-Path) + } + if (![string]::IsNullOrWhiteSpace($Query)){ + $FileNames += Get-TempFileForQuery($Query) + } + $FullFileNameSet = @($FileNames)+@($Files); + $FullFileNameSet += (Join-Path $HelperSQLPath "temp_executeas_cleanup.sql"|Resolve-Path); + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + FileNames = $FullFileNameSet + DatabaseName = $DatabaseName + AdditionalParameters = $AdditionalParameters + PrintSqlOutput = $PrintSqlOutput + } +$dddbefore = Get-Date;Write-Verbose("------->>BEFORE<<-------(tSQLt_Validate.ps1:Invoke-SQLFileOrQuery:Invoke-SqlFile[$($dddbefore|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + $QueryOutput = Invoke-SqlFile @parameters +$dddafter = Get-Date;Write-Verbose("------->>After<<-------(tSQLt_Validate.ps1:Invoke-SQLFileOrQuery:Invoke-SqlFile[$($dddafter|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") +Write-Verbose("Runtime in Milliseconds: $(($dddafter-$dddbefore).TotalMilliseconds)") + return $QueryOutput + } + catch{ + throw + } + finally{ + if($null -ne $tempFile){ + Remove-Item -Path $tempFile.FullName -ErrorAction Ignore + } + } +} + +function Get-TempFileForQuery { + [CmdletBinding()] + [OutputType([string])] + param ( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Query + ) + $tempFile = New-TemporaryFile; + $Query |Set-Content -Path $tempFile + return $tempFile +} + + +function Get-FriendlySQLServerVersion { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$false)][switch]$Quiet + ) + $GetFriendlySQLServerVersionFullPath = (Get-ChildItem -Path ($PSScriptRoot + '/output/*') -include "GetFriendlySQLServerVersion.sql" -Recurse | Select-Object -First 1 ).FullName; + $resultSet = (Invoke-SqlFile -SqlServerConnection $SqlServerConnection -FileNames @($GetFriendlySQLServerVersionFullPath) -DatabaseName 'tempdb'); + $FriendlyVersion = ($resultSet.FriendlyVersion) + if(!$Quiet){Log-Output "Friendly SQL Server Version: $FriendlyVersion"}; + return $FriendlyVersion +} + +function Update-Archive { + param ( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $ArchiveName, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String[]] $FileNamesToInclude + ) + <# Create directory to unpack compressed file #> + $ArchiveDirectory = $ArchiveName + "." + (Get-Date -Format "yyyy-MM-dd-HHmm"); + New-Item -ItemType Directory -Path ".\$ArchiveDirectory"; + + <# Unpack compressed file into newly created directory #> + Expand-Archive -LiteralPath $ArchiveName -DestinationPath $ArchiveDirectory; + + <# Rename original archive file #> + $NewArchiveName = $ArchiveName + ".original"; + Rename-Item -Path $ArchiveName -NewName $NewArchiveName; + + <# Copy new files to include into the archive directory #> + foreach ($FileName in $FileNamesToInclude) { + Copy-Item $FileName -Destination $ArchiveDirectory; + } + + <# Compress files #> + $compress = @{ + Path = $ArchiveDirectory + CompressionLevel = "Fastest" + DestinationPath = $ArchiveName + } + Compress-Archive @compress +} + +function Remove-DirectoryQuietly { + param ( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $Path + ) + if (Test-Path -Path $Path) { + Remove-Item -Path $Path -Recurse -Force + } +} + +Function Remove-ResourceGroup{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ResourceGroupName, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $BuildId); + + Write-Verbose "▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-"; + Write-Verbose ("[{0}]Start processing delete for {1}" -f ((get-date).toString("O")), ($ResourceGroupName)); + + $MyAzResourceGroup = (Get-AzResourceGroup -name "$ResourceGroupName"); + if(("RemovalBy" -in $MyAzResourceGroup.tags.keys) -and (![string]::isnullorempty($MyAzResourceGroup.tags.RemovalBy))) { + $MyAzResourceGroup = $null; + } + if($null -ne $MyAzResourceGroup) { + $Tags = @{}; + Write-Verbose ("Add Tag to {0}" -f $ResourceGroupName); + $Tags = $MyAzResourceGroup.Tags; + $Tags.remove("RemovalBy"); + $Tags += @{"RemovalBy"="$BuildId"}; + $MyAzResourceGroup | Set-AzResourceGroup -Tags $Tags; + Start-Sleep 10; + Write-Verbose ("Confirming Tags are still in place for {0}" -f $ResourceGroupName); + $MyAzResourceGroup = $MyAzResourceGroup | Get-AZResourceGroup | Where-Object {$_.Tags.RemovalBy -eq "$BuildId"}; + $MyAzResourceGroup.Tags | Format-Table; + + if($null -ne $MyAzResourceGroup) { + Write-Verbose "Removing Locks" + $retrievedResourceGroupName = $MyAzResourceGroup.ResourceGroupName; + Get-AzResource -ResourceGroupName $retrievedResourceGroupName | ForEach-Object { + Get-AzResourceLock -ResourceType $_.ResourceType -ResourceName $_.Name -ResourceGroupName $_.ResourceGroupName | ForEach-Object{ + Write-Verbose ("{0} -> {1}" -f $_.ResourceType, $_.ResourceName); + $_ | Remove-AzResourceLock -Force + } + } + Write-Verbose ("Removing RG {0}" -f $retrievedResourceGroupName); + $MyAzResourceGroup | Remove-AzResourceGroup -Force; + } + else { + Write-Verbose ("Tags changed by another process. Resource Group {0} is no longer eligible to be deleted." -f $ResourceGroupName); + } + } + else { + Write-Verbose ("Processing skipped for Resource Group: {0} Build Id: {1}" -f $ResourceGroupName, $BuildId); + } + Write-Verbose ("[{0}]Done processing delete for {1}" -f ((get-date).toString("O")), ($ResourceGroupName)) + Write-Verbose "▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-▀-▄-_-▄-"; +} + +Function Get-SnipContent { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true,ValueFromPipeline=$true)][AllowEmptyString()][string[]]$searchArray, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $startSnipPattern, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][String] $endSnipPattern + ) + begin { + $outputOn = $false; + }; + process { + $searchArray | ForEach-Object { + if($_ -eq $endSnipPattern) { $outputOn = $false }; + if($outputOn) { $_ }; + if($_ -eq $startSnipPattern) { $outputOn = $true }; + } + }; + end { + }; +} + +Function Replace-InFile { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true,ValueFromPipeline=$true)][AllowEmptyString()][string[]]$filePath, + [Parameter(Mandatory=$true)][array] $replacements + ) + begin { + }; + process { + $fileContent = (Get-Content -Path $filePath) + $replacements|ForEach-Object{ + $sv = $_[0] + $rv=$_[1]; + $isRegex = $false; + if($rv -is [array]){ + $isRegex = $true + $rv = $rv[0] + } + Write-Verbose("Replacing >$_< with >$rv<..."); + if($isRegex){ + $fileContent = $fileContent -replace $_, $rv + }else{ + $fileContent = $fileContent.Replace($_, $rv) + } + } + $fileContent | Set-Content -Path $releaseNotesPath + }; + end { + }; +} + +Log-Output($GetUTCTimeStamp.Invoke(),"Done: Loading CommonFunctionsAndMethods"); +Export-ModuleMember -Function Log-Output, Invoke-SqlFile, Get-TempFileForQuery, Get-FriendlySQLServerVersion, Update-Archive +Export-ModuleMember -Function Remove-ResourceGroup, Get-SnipContent, Replace-InFile, Invoke-SQLFileOrQuery, Remove-DirectoryQuietly +Export-ModuleMember -Variable $CommonFunctionsAndMethodsDir, $SQLPrintCurrentTime diff --git a/Build/CreateAssemblyGenerator.exe b/Build/CreateAssemblyGenerator.exe deleted file mode 100644 index b48385a8b..000000000 Binary files a/Build/CreateAssemblyGenerator.exe and /dev/null differ diff --git a/Build/CreateBuildDb.sql b/Build/CreateBuildDb.sql deleted file mode 100644 index 2583be72b..000000000 --- a/Build/CreateBuildDb.sql +++ /dev/null @@ -1,17 +0,0 @@ -GO -IF(DB_ID('$(NewDbName)') IS NOT NULL) -BEGIN - EXEC(' - ALTER DATABASE $(NewDbName) SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE; - USE $(NewDbName); - ALTER DATABASE $(NewDbName) SET SINGLE_USER WITH ROLLBACK IMMEDIATE; - USE tempdb; - DROP DATABASE $(NewDbName); - '); -END -GO -CREATE DATABASE $(NewDbName) COLLATE SQL_Latin1_General_CP1_CS_AS WITH TRUSTWORTHY OFF; --- COLLATE SQL_Latin1_General_CP1_CS_AS -GO -ALTER AUTHORIZATION ON DATABASE::$(NewDbName) TO [tSQLt.Build]; -GO diff --git a/Build/CreateDebugSSMSProject.ps1 b/Build/CreateDebugSSMSProject.ps1 deleted file mode 100644 index 26d2737c3..000000000 --- a/Build/CreateDebugSSMSProject.ps1 +++ /dev/null @@ -1,33 +0,0 @@ - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; -$ParentDir = Split-Path $dir; -$DebugProjectPath = $ParentDir + "/Build_Debug/"; -$OutputPath = $dir + "/output/"; - -.($dir+"\CommonFunctionsAndMethods.ps1"); - -<# Delete all files in Build_Debug except for the ssmssqlproj and .gitignore #> -$FileNamesToExclude = ".gitignore", "Build_Debug.ssmssqlproj"; -Remove-Item -Path $DebugProjectPath -Include "*" -Exclude $FileNamesToExclude -Recurse -Force; - -<# "hello announcement" #> -$VersionFile = $OutputPath + "tSQLtBuild/Version.txt"; -$Version = Get-Content $VersionFile; -Log-Output ("Copying tSQLt build files to local Build_Debug. (Version:" + $Version.Trim() + ")"); - -<# "copy output files and unzip tSQLt.zip and tSQLt.tests.zip" #> -$OutputFilesToCopy = @( - ($OutputPath + "tSQLt/public/tSQLt.zip") - ($OutputPath + "tSQLtBuild/tSQLt.tests.zip") - ($OutputPath + "tSQLtBuild/tSQLtSnippets(SQLPrompt).zip") - ($OutputPath + "tSQLtBuild/Version.txt") - ($OutputPath + "tSQLtBuild/ReadMe.txt") -); -Copy-Item -Path $OutputFilesToCopy -Destination "$DebugProjectPath"; - -$tSQLtZipFile = $DebugProjectPath + "tSQLt.zip"; -Expand-Archive -Path $tSQLtZipFile -DestinationPath $DebugProjectPath; - -$tSQLtTestsZipFile = $DebugProjectPath + "tSQLt.tests.zip"; -Expand-Archive -Path $tSQLtTestsZipFile -DestinationPath $DebugProjectPath; diff --git a/Build/CreateDropClassStatement.ps1 b/Build/CreateDropClassStatement.ps1 deleted file mode 100644 index 21f15af72..000000000 --- a/Build/CreateDropClassStatement.ps1 +++ /dev/null @@ -1,53 +0,0 @@ -$scriptPath = $MyInvocation.MyCommand.Path; -$invocationDir = Split-Path $scriptPath; -$buildPath = $invocationDir +'/'; -$tempPath = $invocationDir + '/temp/tSQLtBuild/'; -$outputPath = $invocationDir + '/output/tSQLtBuild/'; -$sourcePath = $invocationDir + '/../Source/'; -$testUtilPath = $invocationDir + '/../TestUtil/'; - -.($buildPath+"CommonFunctionsAndMethods.ps1"); - -Log-Output '<#--=======================================================================-->' -Log-Output '' -Log-Output '<#--=======================================================================-->' - -$DropClassFileContent = Get-Content -path ($sourcePath+"tSQLt.DropClass.ssp.sql"); -$GetDropItemCmdFileContent = Get-Content -path ($sourcePath+"tSQLt.Private_GetDropItemCmd.sfn.sql"); -$OutputFilePath = $tempPath+"TempDropClass.sql"; - -$DropClassSnip = ($DropClassFileContent | Get-SnipContent -startSnipPattern "/*SnipStart: CreateDropClassStatement.ps1*/" -endSnipPattern "/*SnipEnd: CreateDropClassStatement.ps1*/"); -$DropItemSnip = ($GetDropItemCmdFileContent | Get-SnipContent -startSnipPattern "/*SnipStart: CreateDropClassStatement.ps1*/" -endSnipPattern "/*SnipEnd: CreateDropClassStatement.ps1*/"); -$DropItemParamSnip = ($GetDropItemCmdFileContent | Get-SnipContent -startSnipPattern "/*SnipParamStart: CreateDropClassStatement.ps1*/" -endSnipPattern "/*SnipParamEnd: CreateDropClassStatement.ps1*/"); - -$VariablesString = ($DropItemParamSnip.trim() -join ' ') - -$VariableNames = (Select-String '@\S+' -input $VariablesString -AllMatches|ForEach-Object{$_.matches.Value}); -#$VariableNames - -$DISP1 = ($DropItemSnip | ForEach-Object{ - $s=$_; - for($i = 0;$i -lt $VariableNames.count;$i++){ - $s=$s -replace $VariableNames[$i], ("($"+($i+1)+")") - }; - $s; -}); -$DISP2 = $DISP1.trim() -join ' '; - -$DropItemSnipPrepared = "("+ $DISP2 + ")"; -$RawDropClassStatement = $DropClassSnip -replace 'tSQLt.Private_GetDropItemCmd\s*\(\s*([^,]*)\s*,\s*([^)]*)\s*\)',$DropItemSnipPrepared; - -$DropClassStatement = ($RawDropClassStatement.trim()|Where-Object {$_ -ne "" -and $_ -notmatch "^GO(\s.*)?"}) -join ' '; - -Set-Content -Path $OutputFilePath -Value $DropClassStatement; - - Log-Output '<#--=======================================================================-->' - Log-Output '' - Log-Output '<#--=======================================================================-->' - - -<# TODO ---> Test this: Empty File TempDropClass.sql file should throw an error ---> Test this: If the $tempPath does not exist, BuildHelper.exe seems to currently throw an error, but does that stop the build? ---> Test this: If the $sourcePath does not exist, BuildHelper.exe seems to currently throw an error, but does that stop the build? -#> diff --git a/Build/CreateLogin(tSQLt.Build).sql b/Build/CreateLogin(tSQLt.Build).sql deleted file mode 100644 index 8eee4943a..000000000 --- a/Build/CreateLogin(tSQLt.Build).sql +++ /dev/null @@ -1,61 +0,0 @@ -GO -SET NOCOUNT ON; -GO -USE master; -GO -IF OBJECT_ID('tempdb..#ForceDropDatabase') IS NOT NULL DROP PROCEDURE #ForceDropDatabase; -GO -CREATE PROCEDURE #ForceDropDatabase -@db_name NVARCHAR(MAX) -AS -BEGIN - SET @db_name = PARSENAME(@db_name,1); - DECLARE @cmd NVARCHAR(MAX); - IF(DB_ID(@db_name)IS NOT NULL) - BEGIN - BEGIN TRY - SET @cmd = ' - USE master; - ALTER DATABASE '+QUOTENAME(@db_name)+' SET ONLINE WITH ROLLBACK IMMEDIATE; - ALTER DATABASE '+QUOTENAME(@db_name)+' SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE; - USE '+QUOTENAME(@db_name)+'; - ALTER DATABASE '+QUOTENAME(@db_name)+' SET SINGLE_USER WITH ROLLBACK IMMEDIATE; - '; - EXEC(@cmd); - END TRY BEGIN CATCH END CATCH; - SET @cmd = ' - USE master; - DROP DATABASE '+QUOTENAME(@db_name)+'; - '; - EXEC(@cmd); - END; -END -GO -IF SUSER_SID('tSQLt.Build.SA') IS NOT NULL DROP LOGIN [tSQLt.Build.SA]; -GO -IF SUSER_SID('tSQLt.Build') IS NOT NULL -BEGIN - DECLARE @cmd NVARCHAR(MAX) = - ( - SELECT 'EXEC #ForceDropDatabase '+QUOTENAME(D.name,'''')+';' - FROM sys.databases AS D - JOIN sys.server_principals AS SP - ON D.owner_sid = SP.sid - WHERE SP.name = 'tSQLt.Build' - FOR XML PATH(''),TYPE - ).value('.','NVARCHAR(MAX)'); - EXEC(@cmd); - - DROP LOGIN [tSQLt.Build]; -END; -GO -CREATE LOGIN [tSQLt.Build] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B0 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; -GO -CREATE LOGIN [tSQLt.Build.SA] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B2 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; -GO -EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt.Build.SA', @rolename = N'sysadmin' -EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt.Build', @rolename = N'dbcreator' -GO -EXEC master.sys.sp_executesql N'IF USER_ID(''tSQLt.Build'') IS NOT NULL DROP USER [tSQLt.Build];'; -EXEC master.sys.sp_executesql N'CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build];'; -GO diff --git a/Build/DacpacDeploy.ps1 b/Build/DacpacDeploy.ps1 deleted file mode 100644 index c6961f84e..000000000 --- a/Build/DacpacDeploy.ps1 +++ /dev/null @@ -1,42 +0,0 @@ -<# -- validate that the dacpac is correct by installing tSQLt on one database; installing the dacpac on another database; get the list of names from sys.objects where the name is not Private%; assert that it is the same list --- makesure that the database principal exists, [tSQLt.TestClasses] (maybe) --- -#> -Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlPackagePath -); - -$dir = $PSScriptRoot; - -.($dir+"\CommonFunctionsAndMethods.ps1") - -Log-Output "FileLocation: $dir" - -$BuildPath = $dir+'/'; -$ArtifactPath = $dir + "/output/tSQLt/"; -$PublicArtifactPath = $ArtifactPath + "public/"; -$TempPath = $dir + "/temp/Validate/"; -$DeployDacpacFilesPath = $TempPath + "DeploytSQLtDacpacs/"; -$DacpacsPath = $DeployDacpacFilesPath + "tSQLtDacpacs/"; -Expand-Archive -Path ($PublicArtifactPath+"tSQLt.zip") -DestinationPath $DeployDacpacFilesPath; - -$ServerNameTrimmed = $ServerName.Trim(); -$LoginTrimmed = $Login.Trim("'").Trim(); - -$FriendlySQLServerVersion = Get-FriendlySQLServerVersion -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath; -$DacpacFileName = $DacpacsPath + "tSQLt."+$FriendlySQLServerVersion+".dacpac"; - -$AdditionalParameters = '-v NewDbName="'+$DatabaseName+'"'; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -FileNames ($BuildPath+"CreateBuildDb.sql") -DatabaseName 'tempdb' -AdditionalParameters $AdditionalParameters; - -$SqlConnectionString = Get-SqlConnectionString -ServerName $ServerNameTrimmed -Login $LoginTrimmed -DatabaseName $DatabaseName; -& "$SqlPackagePath/sqlpackage.exe" /a:Publish /tcs:"$SqlConnectionString" /sf:"$DacpacFileName" -if($LASTEXITCODE -ne 0) { - throw "error during deployment of dacpac " + $DacpacFileName; -} - diff --git a/Build/EnableExternalAccess.sql b/Build/EnableExternalAccess.sql deleted file mode 100644 index e1e8b36e3..000000000 --- a/Build/EnableExternalAccess.sql +++ /dev/null @@ -1 +0,0 @@ -EXEC tSQLt.EnableExternalAccess @try = 1; diff --git a/Build/FacadeBuildDacpac.ps1 b/Build/FacadeBuildDacpac.ps1 deleted file mode 100644 index 8bde42dab..000000000 --- a/Build/FacadeBuildDacpac.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlPackagePath -); -<# -Technically this should be called by a matrixed job, so that dacpacs are built for all versions (we support, like not 2005, 2008) -Execute on a target server the Facade scripts - -EXEC Facade.CreateAllFacadeObjects -#> - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; - -.($dir+"\CommonFunctionsAndMethods.ps1"); - -$OutputPath = $dir + "/output/DacpacBuild/"; -$TempPath = $dir + "/temp/DacpacBuild/"; - -$ServerNameTrimmed = $ServerName.Trim(); -$LoginTrimmed = $Login.Trim("'").Trim(); - - -Log-Output "FileLocation: $dir"; -Push-Location; -Set-Location $TempPath; - -$SourceDatabaseName = $DatabaseName+"_src"; -$TargetDatabaseName = $DatabaseName+"_tgt"; -$AdditionalParameters = '-v FacadeSourceDb="'+$SourceDatabaseName+'" FacadeTargetDb="'+$DatabaseName+'_tgt"' - -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath -FileNames @("ResetValidationServer.sql","PrepareServer.sql"); -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath -FileNames "ExecuteFacadeScript.sql" -AdditionalParameters $AdditionalParameters; - -$FriendlySQLServerVersion = Get-FriendlySQLServerVersion -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath; -$FacadeDacpacFileName = "tSQLtFacade."+$FriendlySQLServerVersion+".dacpac"; -$FacadeApplicationName = "tSQLtFacade."+$FriendlySQLServerVersion; -$FacadeConnectionString = Get-SqlConnectionString -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -DatabaseName $TargetDatabaseName; - -& "$SqlPackagePath\sqlpackage.exe" /a:Extract /scs:"$FacadeConnectionString" /tf:"$FacadeDacpacFileName" /p:DacApplicationName="$FacadeApplicationName" /p:IgnoreExtendedProperties=true /p:DacMajorVersion=0 /p:DacMinorVersion=1 /p:ExtractUsageProperties=false -if($LASTEXITCODE -ne 0) { - throw "error during execution of dacpac " + $FacadeDacpacFileName; -} - -Copy-Item -Path $FacadeDacpacFileName -Destination $OutputPath; - -Pop-Location; diff --git a/Build/FacadeBuildScript.ps1 b/Build/FacadeBuildScript.ps1 deleted file mode 100644 index 5a620a0a0..000000000 --- a/Build/FacadeBuildScript.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -New-Item -ItemType "directory" -Path "temp/tSQLtBuild/Facade"; - -../Facade/buildFacadeScripts.ps1 -../FacadeTests/buildFacadeTests.ps1 - -$fileList = @("PrepareServer.sql","ResetValidationServer.sql"); -$tempPath = "temp/tSQLtBuild/Facade/"; - -Copy-Item -Path "temp/tSQLtBuild/*" -Include $fileList -Destination $tempPath; - -$compress = @{ - CompressionLevel = "Optimal" - DestinationPath = "output/tSQLtBuild/tSQLtFacade.zip" - } -Get-ChildItem -Path $tempPath | Compress-Archive @compress - diff --git a/Build/FacadeValidate.ps1 b/Build/FacadeValidate.ps1 deleted file mode 100644 index ee68d1591..000000000 --- a/Build/FacadeValidate.ps1 +++ /dev/null @@ -1,62 +0,0 @@ -<# -- validate that the dacpac is correct by installing tSQLt on one database; installing the dacpac on another database; get the list of names from sys.objects where the name is not Private%; assert that it is the same list --- makesure that the database principal exists, [tSQLt.TestClasses] (maybe) --- -#> -Param( - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlPackagePath, - [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $LogTableName -); - -$scriptpath = $MyInvocation.MyCommand.Path -$dir = Split-Path $scriptpath - -.($dir+"\CommonFunctionsAndMethods.ps1") - -Log-Output "FileLocation: $dir" - -$TempPath = $dir + "/temp/Validate"; -$FacadeFilesPath = $TempPath + "/FacadeDacpacs"; -$TestResultsPath = $TempPath + "/TestResults/TestResults_Facade.xml"; - -$ServerNameTrimmed = $ServerName.Trim(); -$LoginTrimmed = $Login.Trim("'").Trim(); - -Expand-Archive -Path "./output/tSQLt/validation/tSQLtFacade.zip" -DestinationPath $FacadeFilesPath; - -Push-Location; - -$FriendlySQLServerVersion = Get-FriendlySQLServerVersion -ServerName $ServerNameTrimmed -Login "$LoginTrimmed" -SqlCmdPath $SqlCmdPath; -$FacadeFileName = $TempPath + "/tSQLt/FacadeDacpacs/tSQLtFacade."+$FriendlySQLServerVersion+".dacpac"; - -$DacpacDatabaseName = $DatabaseName+"_dacpac"; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -FileNames "CreateBuildDb.sql" -DatabaseName 'tempdb' -AdditionalParameters ('-v NewDbName="'+$DacpacDatabaseName+'"'); - -$SqlConnectionString = Get-SqlConnectionString -ServerName $ServerNameTrimmed -Login $LoginTrimmed -DatabaseName $DacpacDatabaseName; -& "$SqlPackagePath/sqlpackage.exe" /a:Publish /tcs:"$SqlConnectionString" /sf:"$FacadeFileName" -if($LASTEXITCODE -ne 0) { - throw "error during execution of dacpac " + $FacadeFileName; -} - -Set-Location $FacadeFilesPath; - -$AdditionalParameters = '-v FacadeSourceDb="'+$DatabaseName+'_src" FacadeTargetDb="'+$DatabaseName+'_tgt" DacpacTargetDb="'+$DacpacDatabaseName+'"'; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -FileNames "DeployFacadeTests.sql" -AdditionalParameters $AdditionalParameters; - -Set-Location '../tSQLt.tests'; - -$SourceDatabaseName = $DatabaseName+"_src"; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -FileNames ($TempPath + "/tSQLt.tests/TestUtil.sql") -DatabaseName $SourceDatabaseName -AdditionalParameters $AdditionalParameters; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -Query "EXEC tSQLt_testutil.PrepMultiRunLogTable;EXEC tSQLt.SetSummaryError @SummaryError=0;" -DatabaseName $SourceDatabaseName -AdditionalParameters $AdditionalParameters; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -Query "EXEC tSQLt.RunAll;" -DatabaseName $SourceDatabaseName -AdditionalParameters $AdditionalParameters; -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -Query "EXEC tSQLt_testutil.LogMultiRunResult 'DeployFacadeTests.sql';" -DatabaseName $SourceDatabaseName -AdditionalParameters $AdditionalParameters; - -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -FileNames "GetTestResults.sql" -DatabaseName $SourceDatabaseName -AdditionalParameters ('-o "'+$TestResultsPath+'"'); -Exec-SqlFileOrQuery -ServerName $ServerNameTrimmed -Login $LoginTrimmed -SqlCmdPath $SqlCmdPath -Query "EXEC tSQLt.SetSummaryError @SummaryError=1;EXEC tSQLt_testutil.CheckMultiRunResults @noError=1;EXEC tSQLt_testutil.StoreBuildLog @TableName='$LogTableName',@RunGroup='Facade';" -DatabaseName $SourceDatabaseName; - -Pop-Location; - diff --git a/Build/GetTestResults.sql b/Build/GetTestResults.sql deleted file mode 100644 index 0d7ed8aa8..000000000 --- a/Build/GetTestResults.sql +++ /dev/null @@ -1,2 +0,0 @@ -:XML ON -EXEC [tSQLt].[XmlResultFormatter]; diff --git a/Build/LocalBuild.bat b/Build/LocalBuild.bat deleted file mode 100644 index 8e6bde7ba..000000000 --- a/Build/LocalBuild.bat +++ /dev/null @@ -1,95 +0,0 @@ -@ECHO OFF - -ECHO +-------------------------+ -ECHO : Executing Local Build : -ECHO +-------------------------+ -ECHO Parameters: -SET AntHome=%~1 -ECHO AntHome: "%AntHome%" -SET NET4Home=%~2 -ECHO NET4Home: "%NET4Home%" -SET SQLCMDPath=%~3 -ECHO SQLCMDPath: "%SQLCMDPath%" -ECHO SQLVersion: "deprecated" -SET SQLInstanceName=%~4 -ECHO SQLInstanceName: "%SQLInstanceName%" -SET DBName=%~5 -ECHO DBName: "%DBName%" -SET DBLogin=-E -SET AntTarget=all -IF NOT "%~6"=="-v" IF NOT "%~6"=="" SET DBLogin=%~6 -IF NOT "%~7"=="-v" IF NOT "%~7"=="" SET SQLPackagePath=%~7 -IF NOT "%~8"=="-v" IF NOT "%~8"=="" SET AntTarget=%~8 -SET VerboseOutput=ON -IF NOT "%~6"=="-v" IF NOT "%~7"=="-v" IF NOT "%~8"=="-v" IF NOT "%~9"=="-v" SET VerboseOutput=OFF -ECHO DBLogin: "%DBLogin%" -ECHO SQLPackagePath: "%SQLPackagePath%" -ECHO AntTarget: "%AntTarget%" -ECHO VerboseOutput: "%VerboseOutput%" - -REM CALL "%AntHome%\bin\ant" -buildfile Build\tSQLt.experiments.build.xml -Dmsbuild.path="%NET4Home%" -verbose || goto :error -REM goto :EOF - -CALL "powershell.exe" -Command "Set-ExecutionPolicy Bypass -Scope CurrentUser" - -ECHO +-------------------------+ -ECHO : Starting CLR BUILD : -ECHO +-------------------------+ -IF "%VerboseOutput%"=="ON" @ECHO ON -CALL "%AntHome%\bin\ant" -buildfile Build\tSQLt.buildCLR.xml -Dmsbuild.path="%NET4Home%" || goto :error -@ECHO OFF - -ECHO +-------------------------+ -ECHO : Starting tSQLt BUILD : -ECHO +-------------------------+ -IF "%VerboseOutput%"=="ON" @ECHO ON -CALL "%AntHome%\bin\ant" -buildfile Build\tSQLt.build.xml -Dcommit.id="--> LOCALBUILD <--" || goto :error -@ECHO OFF - -ECHO +-----------------------------------+ -ECHO : Creating tSQLt and Facade dacpacs : -ECHO +-----------------------------------+ -IF "%VerboseOutput%"=="ON" @ECHO ON -CALL "powershell.exe" -File Build\SetupDacpacBuild.ps1 -ErrorAction Stop || goto :error -@REM -----------------------------------------------------------------------------This space character is utterly important! --------------v -CALL "powershell.exe" -File Build\FacadeBuildDacpac.ps1 -ErrorAction Stop -ServerName "%SQLInstanceName%" -DatabaseName "%DBName%" -Login " %DBLogin%" -SqlCmdPath "%SQLCMDPath%" -SqlPackagePath "%SQLPackagePath%" || goto :error -CALL "powershell.exe" -File Build\BuildtSQLtDacpac.ps1 -ErrorAction Stop -ServerName "%SQLInstanceName%" -DatabaseName "%DBName%_dacpac_src" -Login " %DBLogin%" -SqlCmdPath "%SQLCMDPath%" -SqlPackagePath "%SQLPackagePath%" || goto :error -@ECHO OFF - -ECHO +-------------------------+ -ECHO : Repackage zip file : -ECHO +-------------------------+ -IF "%VerboseOutput%"=="ON" @ECHO ON -CALL "powershell.exe" -File Build\BuildtSQLtZip.ps1 -ErrorAction Stop || goto :error -@ECHO OFF - -ECHO +----------------------------+ -ECHO : Create Build Debug Project : -ECHO +----------------------------+ -IF "%VerboseOutput%"=="ON" @ECHO ON -CALL "powershell.exe" -File Build\CreateDebugSSMSProject.ps1 -ErrorAction Stop || goto :error -@ECHO OFF - -ECHO +-------------------------+ -ECHO : Validating BUILD : -ECHO +-------------------------+ -FOR /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set LogTableName=tempdb.dbo.[%%j] -ECHO LogTableName: %LogTableName% - -IF "%VerboseOutput%"=="ON" @ECHO ON -@REM -----------------------------------------------------------------------------This space character is utterly important! ----v -CALL "%AntHome%\bin\ant" "%AntTarget%" -buildfile Build\tSQLt.validatebuild.xml -Ddb.server="%SQLInstanceName%" -Ddb.name=%DBName% -Ddb.login=" %DBLogin%" -Dsqlcmd.path="%SQLCMDPath%" -Dsqlpackage.path="%SQLPackagePath%" -Dlogtable.name="%LogTableName%" || goto :error -@ECHO OFF - -ECHO +-------------------------+ -ECHO : BUILD SUCCEEDED : -ECHO +-------------------------+ -goto :EOF - -:error -@ECHO OFF -ECHO +-------------------------+ -ECHO : !!! BUILD FAILED !!! : -ECHO +-------------------------+ -exit /b %errorlevel% - diff --git a/Build/LocalBuild.ps1 b/Build/LocalBuild.ps1 new file mode 100644 index 000000000..e8bd67647 --- /dev/null +++ b/Build/LocalBuild.ps1 @@ -0,0 +1,110 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $ServerName = 'localhost,1433', + [Parameter(Mandatory=$true, ParameterSetName = 'UserPass')][ValidateNotNullOrEmpty()][string] $UserName = "sa" , + [Parameter(Mandatory=$true, ParameterSetName = 'UserPass')][ValidateNotNullOrEmpty()][securestring] $Password = (ConvertTo-SecureString "P@ssw0rd" -AsPlainText), + [Parameter(Mandatory=$true, ParameterSetName = 'TrustedCon')][ValidateNotNullOrEmpty()][switch] $TrustedConnection, + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $DatabaseName = 'tSQLt.TmpBuild.DacPacBuild', + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $pfxFilePath = (Join-Path $env:TSQLTCERTPATH "tSQLtOfficialSigningKey.pfx" |Resolve-Path), + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][securestring] $pfxPassword = (ConvertTo-SecureString -String "$env:TSQLTCERTPASSWORD" -Force -AsPlainText), + [Parameter(Mandatory=$false)][switch]$KeepTemp, + [Parameter(Mandatory=$false, ParameterSetName="IgnoreMe")][string]$IgnoreMe +) +$PSDefaultParameterValues = $PSDefaultParameterValues.clone() +$PSDefaultParameterValues += @{'*:ErrorAction' = 'Stop'} + +Write-Verbose "Starting execution of LocalBuild.ps1" +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +$cfam = (Join-Path $invocationDir "CommonFunctionsAndMethods.psm1" | Resolve-Path) +Write-Verbose "Attempting to load module from: $cfam" +Import-Module "$cfam" -Force -Verbose +. (Join-Path $invocationDir 'SQLServerConnection.ps1'); + +function CleanTemp { + param ( + [Parameter(Mandatory=$false)][bool]$KeepTemp = $false + ) + if(! $KeepTemp){ + if (Test-Path -Path "temp") { + Remove-Item -Path "temp" -Recurse -Force + } + } +} + +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +try{ + + Log-Output(''); + Log-Output("+--------------------------------------------------------------------+"); + Log-Output("| ***** Executing Local tSQLt Build ***** |"); + Log-Output("+--------------------------------------------------------------------+"); + Log-Output(''); + + if($TrustedConnection){ + Log-Output('Selecting Trusted Connection') + $SqlServerConnection = [SqlServerConnection]::new($ServerName,"LocalBuild"); + }else{ + Log-Output('Selecting UserName/Password Connection') + $SqlServerConnection = [SqlServerConnection]::new($ServerName,$UserName,$Password,"LocalBuild"); + } + + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Cleaning Environment :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + if (Test-Path -Path "output") { + Remove-Item -Path "output" -Recurse -Force + } + CleanTemp; + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Starting CLR Build :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + & ./tSQLt_BuildCLR.ps1 -pfxFilePath $pfxFilePath -pfxPassword $pfxPassword + CleanTemp $KeepTemp; + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Starting tSQLt Build :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + & ./tSQLt_Build.ps1 + CleanTemp $KeepTemp; + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Starting tSQLt Tests Build :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + & ./tSQLt_BuildTests.ps1 + CleanTemp $KeepTemp; + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Starting tSQLt DacPac Build :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') +# Write-Warning($SqlServerConnection) + & ./tSQLt_BuildDacpac.ps1 -SqlServerConnection $SqlServerConnection -DacPacDatabaseName $DatabaseName + CleanTemp $KeepTemp; + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Packaging tSQLt & DACPACs :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + & ./tSQLt_BuildPackage.ps1 + CleanTemp $KeepTemp; + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Build Finished :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + +} +catch{ + throw; +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/LocalValidate.ps1 b/Build/LocalValidate.ps1 new file mode 100644 index 000000000..dd14882a0 --- /dev/null +++ b/Build/LocalValidate.ps1 @@ -0,0 +1,64 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $ServerName = 'localhost,1433', + [Parameter(Mandatory=$true, ParameterSetName = 'UserPass')][ValidateNotNullOrEmpty()][string] $UserName = "sa" , + [Parameter(Mandatory=$true, ParameterSetName = 'UserPass')][ValidateNotNullOrEmpty()][securestring] $Password = (ConvertTo-SecureString "P@ssw0rd" -AsPlainText), + [Parameter(Mandatory=$true, ParameterSetName = 'TrustedCon')][ValidateNotNullOrEmpty()][switch] $TrustedConnection, + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $DatabaseName = 'tSQLtValidateBuild', + [Parameter(Mandatory=$false, ParameterSetName="IgnoreMe")][string]$IgnoreMe +) +$PSDefaultParameterValues = $PSDefaultParameterValues.clone() +$PSDefaultParameterValues += @{'*:ErrorAction' = 'Stop'} + +Write-Verbose "Starting execution of LocalBuild.ps1" +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +$cfam = (Join-Path $invocationDir "CommonFunctionsAndMethods.psm1" | Resolve-Path) +Write-Verbose "Attempting to load module from: $cfam" +Import-Module "$cfam" -Force -Verbose +. (Join-Path $invocationDir 'SQLServerConnection.ps1'); + + +try{ + + if($TrustedConnection){ + Log-Output('Selecting Trusted Connection') + $SqlServerConnection = [SqlServerConnection]::new($ServerName,"LocalBuild"); + }else{ + Log-Output('Selecting UserName/Password Connection') + $SqlServerConnection = [SqlServerConnection]::new($ServerName,$UserName,$Password,"LocalBuild"); + } + + Log-Output(''); + Log-Output("+--------------------------------------------------------------------+"); + Log-Output("| ***** Executing Local tSQLt Build Validation ***** |"); + Log-Output("+--------------------------------------------------------------------+"); + Log-Output(''); + + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Starting Build Validation :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + MainTestDb = 'tSQLt.TmpBuild.ValidateBuild' + DacpacTestDb = 'tSQLt.TmpBuild.ValidateDacPac' + ExampleTestDb = 'tSQLt.TmpBuild.ValidateExample' + } + + & ./tSQLt_Validate.ps1 @parameters + + Log-Output('+ - - - - - - - - - - - - - - - - - +') + Log-Output(': Build Validation Finished :') + Log-Output('+ - - - - - - - - - - - - - - - - - +') + + +} +catch{ + throw; +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/LocalValidateBuild.bat b/Build/LocalValidateBuild.bat deleted file mode 100644 index 8d466536c..000000000 --- a/Build/LocalValidateBuild.bat +++ /dev/null @@ -1,50 +0,0 @@ -@ECHO OFF - -ECHO +----------------------------------+ -ECHO : Executing Validate Build : -ECHO +----------------------------------+ -ECHO Parameters: -SET AntHome=%~1 -ECHO AntHome: "%AntHome%" -SET NET4Home=%~2 -ECHO NET4Home: "%NET4Home%" -SET SQLCMDPath=%~3 -ECHO SQLCMDPath: "%SQLCMDPath%" -ECHO SQLVersion: "deprecated" -SET SQLInstanceName=%~4 -ECHO SQLInstanceName: "%SQLInstanceName%" -SET DBName=%~5 -ECHO DBName: "%DBName%" -SET DBLogin=-E -IF NOT "%~6"=="-v" IF NOT "%~6"=="" SET DBLogin=%~6 -IF NOT "%~7"=="-v" IF NOT "%~7"=="" SET SQLPackagePath=%~7 -SET VerboseOutput=ON -IF NOT "%~6"=="-v" IF NOT "%~7"=="-v" IF NOT "%~8"=="-v" SET VerboseOutput=OFF -REM ECHO DBLogin: "%DBLogin%" -ECHO SQLPackagePath: "%SQLPackagePath%" -ECHO VerboseOutput: "%VerboseOutput%" - -CALL "powershell.exe" -Command "Set-ExecutionPolicy Bypass -Scope CurrentUser" - -ECHO +----------------------------------+ -ECHO : VALIDATING BUILD : -ECHO +----------------------------------+ -FOR /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set LogTableName=tempdb.dbo.[%%j] -ECHO LogTableName: %LogTableName% - -IF "%VerboseOutput%"=="ON" @ECHO ON -@REM -----------------------------------------------------------------------------This space character is utterly important! ----v -CALL "ant" -buildfile Build\tSQLt.validatebuild.xml -Ddb.server="%SQLInstanceName%" -Ddb.name=%DBName% -Ddb.login=" %DBLogin%" -Dsqlcmd.path="%SQLCMDPath%" -Dsqlpackage.path="%SQLPackagePath%" -Dlogtable.name="%LogTableName%" || goto :error -@ECHO OFF - -ECHO +----------------------------------+ -ECHO : VALIDATE BUILD SUCCEEDED : -ECHO +----------------------------------+ -goto :EOF - -:error -@ECHO OFF -ECHO +----------------------------------+ -ECHO : !!! BUILD FAILED !!! : -ECHO +----------------------------------+ -exit /b %errorlevel% diff --git a/Build/Readme.md b/Build/Readme.md new file mode 100644 index 000000000..d130bf7fd --- /dev/null +++ b/Build/Readme.md @@ -0,0 +1,13 @@ +# Building tSQLt + +To build tSQLt on your local machine, clode the repository in a local folder: + +`git clone https://` + +Open that folder in Visual Studio Code, aka VSC (Open Source, download from [https://code.visualstudio.com/download](https://code.visualstudio.com/download).) + +You also need Docker Dektop (Free for non-commercial use, Download from [https://www.docker.com/products/docker-desktop/](https://www.docker.com/products/docker-desktop/).) This might work with other container platforms, too. + +Once ready, type `>Dev Containers: Open Folder in Container...` into the top bar in VSC and hit Enter. + +This starts up your development container, that includes all the software needed to build tSQLt. \ No newline at end of file diff --git a/Build/ReleaseNotes.txt b/Build/ReleaseNotes.txt index 980af74fd..0d8b132b1 100644 --- a/Build/ReleaseNotes.txt +++ b/Build/ReleaseNotes.txt @@ -1,552 +1,552 @@ -tSQLt Release Notes -=================== -An online version of these release notes is available at: -http://tsqlt.org/category/release-notes/ - ---------------------------- -Release: VLATEST-BUILD-NUMBER -Date: 2022-02-16 - -BUG FIXES: - -1. tSQLt does not install on case sensitive *server*: https://github.com/tSQLt-org/tSQLt/issues/155 -2. Changed build order to eliminate warning about tSQLt.Private_MarktSQLt_TempObject: https://github.com/tSQLt-org/tSQLt/pull/151 - -NEW FEATURES: - -1. N/A - -MISCELLANEOUS: - -1. Microsoft changed the paths for sqlpackage and sqlcmd on the build agent image (windows-2019) - ---------------------------- -Release: V1.0.8043.39707 -Date: 2022-01-08 - -BUG FIXES: - -N/A - -NEW FEATURES: - -1. SpyProcedure has a new optional parameter, @CallOriginal -2. SpyProcedure provides the variable @SpyProcedureOriginalObjectName within the CommandToExecute -3. NoTransaction test annotation --[@tSQLt:NoTransaction](@CleanUpProcedureName) - This annotation causes the test to be executed outside of a transaction. The @CleanUpProcedureName procedure is executed after the test completes. -4. UndoTestDoubles, useful when test double procedures like tSQLt.FakeTable are executed outside of a transaction -5. FakeFunction allows FakeDataSource to be a "VALUES" clause - -MISCELLANEOUS: - -1. Reduced the complexity of building and testing tSQLt -2. Removed dependency on Private_NullCellTable table -3. Installation of tSQLt can handle more edge cases -4. Standardized error messages -5. For tSQLt contributors: New build target 'tSQLtOnly', which skips Facade validation steps - ---------------------------- -Release: V1.0.7950.1808 - -BUG FIXES: - -1. Removed unexpected facade objects (aka ufos) from tSQLt dacpacs. - -NEW FEATURES: - -N/A - -MISCELLANEOUS: - -N/A - ---------------------------- -Release: V1.0.7942.19440 - -BUG FIXES: - -N/A - -NEW FEATURES: - -1. tSQLt can now be installed using DACPACs as well as the original tSQLt.class.sql script. Note: Unlike the original tSQLt.class.sql script, DACPACs are SQL Server version specific. -2. tSQLt.FriendlySQLServerVersion function reports the SQL Server Version as a string with commonly used moniker e.g. 2008R2 or 2019. -3. tSQLt is now certified for SQL Server on Linux. - -MISCELLANEOUS: - -1. Created GitHub Action for building and testing tSQLt on MSSQL 2017 and 2019 using Redgate Spawn. -2. Refactored Azure DevOps Pipeline to use more powerful VMs and azcli to create the SQLVM with a bicep file. -3. Migrated parts of the tSQLt build from ant to PowerShell. -4. Prototyped using AKS (Azure Kubernetes Service) to host MSSQL 2014, 2016, 2017, and 2019. -5. Prototyped Facade dacpacs for use in Visual Studio when developing tests with tSQLt. Ultimately we chose a full tSQLt dacpac for this work, but continue to retain the original Facade code and tests. - - ---------------------------- -Release: V1.0.7682.21917 - -BUG FIXES: - -1. Fix sysname casing for case-sensitive databases. Fixed by Trygve Wastvedt (https://github.com/twastvedt). - -2. Fixed issue in tSQLt.Private_GetFullTypeName not handling fractional seconds precision on date and time types. Fixed by saperry (https://github.com/saperry). - -NEW FEATURES: - -1. FakeFunction now accepts non-functions as data sources for example tables or SELECT statements. Contributed by Dmitrij Kultasev (https://github.com/dkultasev). - -MISCELLANEOUS: - -1. For tSQLt contributors: allow SQL Server Authentication for build - ---------------------------- -Release: V1.0.7597.5637 - -BUG FIXES: - -N/A - -NEW FEATURES: - -1. The tSQLt CLR is now signed with a new key: - - Public key (hash algorithm: sha1): - 0024000004800000940000000602000000240000525341310004000001000100b9af416ad8dfed - ec08a5652fa257f1242bf4ed60ef5a7b84a429604d62c919c5663a9c7710a7c5df9953b69ec89f - ce85d71e051140b273f4c9bf890a2bc19c48f22d7b1f1d739f90eebc5729555f7f8b63ed088bbb - 083b336f7e38b92d44cfe1c842f09632b85114772ff2122bc638c78d497c4e88c2d656c166050d - 6e1ef394 - - Public key token is e8fff6f136d7b53e - -2. Several improvements to the build process, including switching from NAnt to Ant - -3. New prepare server process (this fixes all installation issues with 2017 and 2019) - - Before installing tSQLt, you can now run the PrepareServer.sql that is part of the tSQLt.zip download. - It automatically enables CLR and installs a server certificate that allows the installation of the CLR. - There is no need to disable strict CLR security on the server nor do you need to modify database security settings. - Executing the script requires SA permissions, but needs to be done only once per server. - - Reminder: If you are using the tSQLt.NewConnection feature, - you need to execute tSQLt.EnableExternalAccess after each installation of tSQLt. - -4. Annotations - - tSQLt now allows for test case annotations to modify test behavior. The annotations implemented so far are: - - --[@tSQLt:MaxSqlMajorVersion](@MaxVersion) <-- Skips the test if the major version of SQL Server is > @MaxVersion - --[@tSQLt:MinSqlMajorVersion](@MinVersion) <-- Skips the test if the major version of SQL Server is < @MinVersion - --[@tSQLt:Skip](@SkipReason) <-- Skips the test and reports @SkipReason as reason in the output - -5. Implemented a CI pipeline for tSQLt itself in Azure DevOps - ---------------------------- -Release: V1.0.5873.27393 - -BUG FIXES: - -1. Fixed error message in tSQLt.FakeTable - -2. tSQLt.DropClass now handles already quoted names correctly - -NEW FEATURES: - -1. The tSQLt CLR is now signed with a new key: - Public Key Token = 0x7722217d36028e4c - Public Key: 0x0602000000240000525341310004000001000100F7D9A45F2B508C2887A8794B053CE5DEB28743B7C748FF545F1F51218B684454B785054629C1417D1D3542B095D80BA171294948FCF978A502AA03240C024746B563BC29B4D8DCD6956593C0C425446021D699EF6FB4DC2155DE7E393150AD6617EDC01216EA93FCE5F8F7BE9FF605AD2B8344E8CC01BEDB924ED06FD368D1D0 - The password required to sign an assembly with this key is no longer part of the code - base. This was necessary to be able to provide a secure method of installing tSQLt not - requiring the database to be set to TRUSTWORTHY anymore. - -2. tSQLt.Info() now returns the public key token of the assembly's signing key in - the CLRSigningKey column - -3. tSQLt.RunNew executes all tests in test classes (schemata) that were created with - tSQLt.NewTestClass after the last call to tSQLt.Reset - -4. tSQLt.InstallExternalAccessKey installs the required objects in the master database - to allow tSQLt to execute with EXTERNAL_ACCESS without the database being TRUSTWORTHY - -5. tSQLt.RemoveExternalAccessKey removes those objects from the master database - -6. tSQLt.EnableExternalAccess can be used to manually enable and disable EXTERNAL_ACCESS - -7. tSQLt automatically tries to enable EXTERNAL_ACCESS, each time any "run" method is called. - Enabling EXTERNAL_ACCESS is possible when either the database is TRUSTWORTHY and owned - by a server principal with EXTERNAL_ACCESS_ASSEMBLY permission, or if - tSQLt.InstallExternalAccessKey has been executed before on the server. - - This feature establishes backward compatibillity but comes at a performance cost. - It might therefore be removed in a future version. - -8. tSQLt detects at the beginning of each execution, if the requirements to enable - EXTERNAL_ACCESS are not any longer fulfilled. If the assembly is still marked as - EXTERNAL_ACCESS, the execution is halted immediately, and an error is reported - back to the caller. - -9. tSQLt checks at the beginning of each execution, if the installed assembly's version - matches the version of the T-SQL code. If a mismatch is detected, the execution is - immediately halted and an error is reported back to the caller. - -A. tSQLt.Run now allows a test result formatter to be passed in in the @TestResultFormatter - parameter. If that parameter is omitted or NULL, the default result formatter is used. - -OTHER: - -1. Cleaned up several procedures and tests - -2. Removed extraneous DROP statements from tSQLt install file. - ---------------------------- -Release: V1.0.5793.20044 - -BUG FIXES: -1. AssertEqualsTableSchema now handles gaps in column_id values correctly (thanks Greg L.) -2. Fixed handling of empty messages in AssertEmptyTable - -NEW FEATURES: -1. AssertStringIn asserts that a string value is element of a set of string values -2. ApplyConstraint can now apply cascading actions on foreign keys -3. FakeTable can now fake synonyms of tables and view (in the same database only, for now) - -OTHER: - ---------------------------- -Release: V1.0.5686.18945 - -BUG FIXES: -1. The XML output now validates against the JUnit test result XML schema at - https://raw.githubusercontent.com/windyroad/JUnit-Schema/master/JUnit.xsd - While there is no "official" JUnit schema, the above is the one that is - referenced most often online. - -2. tSQLt.DropClass now handles XML schemata correctly. - -3. All tSQLt assertions can now be called with a @Message parameter. In case of a - failure, the value of that parameter will be output before the default failure - message. - For backward compatibility, tSQLt.AssertEqualsTable still has a @FailMsg - parameter. Its use is now deprecated. - -NEW FEATURES: -1. tSQLt.Info() now returns the version and build of the SQL Server Instance it is installed on: - - SELECT * FROM tSQLt.Info() AS I; - - Version ClrVersion SqlVersion SqlBuild - -------------- -------------- ---------- -------- - 1.0.5479.30419 1.0.5479.30419 12.00 4213.00 - -2. Verbose execution mode - Executing EXEC tSQLt.SetVerbose @Verbose = 1; before running the tests will cause - tSQLt to output the test name at the beginning and the end of each test's execution. - That makes it easier in large test suites to find the output of a particular test. - -3. tSQLt.RunC - The new procedure tSQLt.RunC behaves identical to tSQLt.Run. However, instead of - expecting the test (class) name in a parameter, it parses the INPUTBUFFER and - extracts the name from a specially formed comment: - - EXEC tSQLt.RunC;--Run_Methods_Tests.[test tSQLt.RunC calls tSQLt.Run with everything after ;-- as @TestName] - - This makes for a more powerful SQL Query shortcut in SSMS as test names now do not have to be quoted anymore. - -4. tSQLt.AssertEqualsTableSchema - tSQLt.AssertEqualsTableSchema is called like tSQLt.AssertEqualsTable. Instead of - the table contents, it compares the columns including name, datatype, collation, - NULL-ability and identity property. - -5. The test runner now captures start and end time for each test. This information - is included in the XML output. The default output contains the execution duration - for each test. - -6. Both tSQLt.SpyProcedure and tSQLt.FakeFunction now handle table type parameters. - The content of a table type parameter in a spied procedure is converted into - XML and included in the _SpyProcedureLog table. - -OTHER: - -1. Farewell Sourceforge - Because of several issues over the last months and because of even more complaints - about Sourceforge's business practices by tSQLt users, we decided to find a more appropriate space. - The official downloads are now available directly on tSQLt.org. The source code - repository will find its new home either on github or bitbucket over the next few days. - -2. The fail message of tSQLt.AssertEqualsString is now broken into two lines - with aligned string values for easier comparison. - -3. The installation script now prints a welcome message. - - - ---------------------------- -Release: V1.0.5325.27056 - -BUG FIXES: -1. FakeTable now handles CHAR UDTs - -NEW FEATURES: -1. SQL 2014 now officially supported -2. tSQLt.ApplyConstraint now handles UNIQUE and PRIMARY KEY constraints -3. tSQLt.DropClass now handles UDTs -4. tSQLt.ExpectNoException can be followed by tSQLt.ExpectException -5. Added @IfExists parameter to tSQLt.RemoveObject -6. Added tSQLt.RemoveObjectIfExists -7. Added tSQLt.AssertObjectDoesNotExist - ---------------------------- -Release: V1.0.5137.39257 - -NEW FEATURES: -1. added tSQLt.RenameClass - - ---------------------------- - -Release: V1.0.5071.16906 - -NEW FEATURES: -1. added tSQLt.FakeFunction -2. added @ExpectedErrorNumber parameter to tSQLt.ExpectException - - ---------------------------- - -Release: V1.0.4969.33062 - -NEW FEATURES: -1. tSQLt.ApplyTrigger -2. tSQLt.ExpectNoException -OTHER: -1. The output of a test that errors out now contains the severity and state of that error. - ---------------------------- - -Release: V1.0.4941.23369 - -BUG FIXES: -1. tSQLt.Fail now works when transaction is in an uncommittable state. -NEW FEATURES: -1. tSQLt.AssertNotEquals -2. tSQLt.AssertEmptyTable -3. tSQLt.ExpectException -OTHER: -1. We have now a set of snippets for Red Gate SQL Prompt to support test development - Instructions of how to get them are available on our downloads page: http://tSQLt.org/downloads - ---------------------------- - -Release: V1.0.4822.19862 - -BUG FIXES: -1. Corrected defect in AssertEqualsTable where the custom error message was not being displayed. -NEW FEATURES: -1. Added tSQLt.RemoveObject procedure. - ---------------------------- - -Release: V1.0.4735.30771 - -BUG FIXES: -1. AssertEqualsTable did not quote columns. -NEW FEATURES: -1. Added AssertLike procedure. -2. Added support for multi-column foreign keys in ApplyConstraint. - ---------------------------- - -Release: V1.0.4721.29450 - -BUG FIXES: -1. When executing tSQLt.Run on an individual test, the setup procedure was sometimes not - called based on the case of the setup procedure name. -OTHER: -1. Added StubRecord procedure back in, however it is marked as 'not supported'. - ---------------------------- - -Release: V1.0.4643.26915 - -OTHER: -1. Removed unused procedure: StubRecord -2. Improved the performance of AssertEqualsTable -3. AssertEqualsTable now gives reasonalbe error messages for unsupported datatypes. More - information on unsupported datatypes is available on the documentation page for - AssertEqualsTable: http://tsqlt.org/user-guide/assertions/assertequalstable/ - ---------------------------- -Release: V1.0.4504.21220 - -BUG FIXES: -1. tSQLt.NewTestClass now does not drop schema objects if the schema is not a test class - ---------------------------- -Release: V1.0.4496.29340 - -BUG FIXES: -1. tSQLt.ResultSetFilter now supports data types introduced in SQL Server 2008 and CLR - datatypes. -2. tSLQt.AssertResultSetsHaveSameMetaData now ignores "hidden" columns. For example, - when comparing the metadata of a view, this procedure had been including underlying - columns. - ---------------------------- -Release: V1.0.4462.23207 - -NEW FEATURES: -1. tSQLt.FakeTable now supports @Defaults parameter. If @Defaults = 1 default - constraints will be preserved on columns. -2. tSQLt.FakeTable now supports @ComputedColumns parameter. If - @ComputedColumns = 1 computed columns will be preserved. - ---------------------------- - -Release: 1.0.4413.31717 - -NEW FEATURES: -1. tSQLt.Info() now reports Version and CLRVersion. These should always match! -2. tSQLt.FakeTable now supports @Identity parameter. If @Identity = 1 the - identity property of the table is preserved. - ---------------------------- - -Release: V1.0.4357.27914 - -BUG FIXES: -1. tSQLt.SpyProcedure can handle user defined types. User defined types may be in schemas and - may also be not nullable. - -NEW FEATURES: -1. SetUp can be named in any combination of upper or lower case characters (e.g. setup, SETUP, - SeTuP, etc). ---------------------------- - -Release: V1.0.4351.28410 - -BUG FIXES: -1. tSQLt.NewTestClass now handles schema names with spaces and other special characters -2. tSQLt.NewTestClass now handles if a quoted name is passed for the new schema name - -NEW FEATURES: -1. tSQLt.Uninstall removes tSQLt from the database -2. tSQLt.RunWithXmlResults executes like tSQLt.Run, but produces results is XML -3. tSQLt.TestClasses is a view that lists properties of test classes -4. tSQLt.Tests is a view that lists properties of test cases -5. Example.sql includes an example database and is referenced by the updated Quick Start - (http://tsqlt.org/quick-start) -6. tSQLt.Info() provides information about the installed version of tSQLt. - -OTHER: -1. New numbering system for the tSQLt builds. The current version is: V1.0.4351.28410 ---------------------------- - -build.12: - -BUG FIXES: -1. tSQLt.Fail now handles NULL values as parameters. -2. Corrected XmlResultFormatter to have root element of 'testsuites' instead of 'root'. -This improves compatibility with more continuous integration servers. - -NEW FEATURES: -1. FakeTable now handles a single parameter, combining the schema and table name. -This makes FakeTable more consistent with other methods in tSQLt. -2. ApplyConstraint now handles two parameters, combining the schema and table -name as the first parameter. This makes ApplyConstraint more consistent with other -methods in tSQLt. - ---------------------------- - -build.11: - -BUG FIXES: -1. ApplyConstraint for a Foreign Key that references a Faked Table is fixed. -2. SetClrEnabled.sql utlity file now handles database names with spaces. -3. Test cases whose names contain a percent sign are now displayed correctly -in the test case output. - -NEW FEATURES: -1. Warnings about renaming objects displayed when executing FakeTable or -ApplyConstraint are now hidden. -2. New method: tSQLt.SuppressOutput suppresses the console output that would -be displayed by executing a command. -3. New method: tSQLt.CaptureOutput logs the console output from executing a -command into the tSQLt.CaptureOutputLog table. - ---------------------------- - -build.10: - -BUG FIXES: -1. Standardized capitalization of table, column, procedure and function names. - -NEW FEATURES: -1. Added support for case sensitive databases. - ---------------------------- - -build.9: - -BUG FIXES: -1. When using tSQLt.Run or tSQLt.RunTestClass, if an object name on the dbo -schema had the same name as a test class, the test class could not be executed. - -2. If the output of an AssertTableEquals or the length of a test case name was -too long, an error was be produced. - -NEW FEATURES: -1. A new procedure, tSQLt.NewConnection, was added which allows statements to -be executed synchronously in a different connection context. - ---------------------------- - -build.8a: - -BUG FIXES: -1. When executing tSQLt.ResultSetFilter, if the result set metadata contained -hidden columns then those columns would be returned in the result set output. -The values of those columns would be null. Hidden columns are typically present -when the base tables of a result set contain primary keys or other constraints -which were not selected. tSQLt.ResultSetFilter has been updated to not return -the hidden columns. - ---------------------------- - -build.8: - -NEW FEATURES: -1. SpyProcedure now supports output parameters. Details are available in the -User Guide. See: http://www2.sqlity.net/tsqlt/spyprocedure - -2. The first major sections of the User Guide are now available at: -http://www.tsqlt.org - On the right hand side is a link for the User Guide. - ---------------------------- - -build.7: - -IMPORTANT: tSQLt now utilizes CLR (Common Language Runtime) stored procedures. -In order to install tSQLt, CLRs must be enabled in SQL Server. The -SetClrEnabled.sql file has the command which enables CLRs. If CLRs are not -already enabled, this command must be executed before installing tSQLt. - -NEW FEATURES: -1. A new procedure tSQLt.RunAll, executes all test classes created with the -tSQLt.NewTestClass procedure. - -2. Added procedure tSQLt.AssertResultSetsHaveSameMetaData which allows the -meta data of two result sets to be compared. This compares several properties -of each column of the result set including the column name, data type, length, -precision, scale and other properties. - -3. Added procedure tSQLt.ResultSetFilter which returns a single result set from -a statement which produces multiple result sets. For example, you want to test -a stored procedure which executes several select statements. You can now use -ResultSetFilter to choose which result set to emit, and therefore you can -capture that result set into a table for use with tSQLt.AssertEqualsTable. - -4. The results of running tests can now be output in an XML format. After -calling one of the tSQLt.Run... procedures to execute your test cases, you -can call tSQLt.XmlResultFormatter to display the results in XML. The format is -compatible with CruiseControl and can be merged into a build log the same way -that a JUnit test report is merged. +tSQLt Release Notes +=================== +An online version of these release notes is available at: +http://tsqlt.org/category/release-notes/ + +--------------------------- +Release: V1.1.8738.27883 +Date: 2022-02-16 + +BUG FIXES: + +1. tSQLt does not install on case sensitive *server*: https://github.com/tSQLt-org/tSQLt/issues/155 +2. Changed build order to eliminate warning about tSQLt.Private_MarktSQLt_TempObject: https://github.com/tSQLt-org/tSQLt/pull/151 + +NEW FEATURES: + +1. N/A + +MISCELLANEOUS: + +1. Microsoft changed the paths for sqlpackage and sqlcmd on the build agent image (windows-2019) + +--------------------------- +Release: V1.0.8043.39707 +Date: 2022-01-08 + +BUG FIXES: + +N/A + +NEW FEATURES: + +1. SpyProcedure has a new optional parameter, @CallOriginal +2. SpyProcedure provides the variable @SpyProcedureOriginalObjectName within the CommandToExecute +3. NoTransaction test annotation --[@tSQLt:NoTransaction](@CleanUpProcedureName) + This annotation causes the test to be executed outside of a transaction. The @CleanUpProcedureName procedure is executed after the test completes. +4. UndoTestDoubles, useful when test double procedures like tSQLt.FakeTable are executed outside of a transaction +5. FakeFunction allows FakeDataSource to be a "VALUES" clause + +MISCELLANEOUS: + +1. Reduced the complexity of building and testing tSQLt +2. Removed dependency on Private_NullCellTable table +3. Installation of tSQLt can handle more edge cases +4. Standardized error messages +5. For tSQLt contributors: New build target 'tSQLtOnly', which skips Facade validation steps + +--------------------------- +Release: V1.0.7950.1808 + +BUG FIXES: + +1. Removed unexpected facade objects (aka ufos) from tSQLt dacpacs. + +NEW FEATURES: + +N/A + +MISCELLANEOUS: + +N/A + +--------------------------- +Release: V1.0.7942.19440 + +BUG FIXES: + +N/A + +NEW FEATURES: + +1. tSQLt can now be installed using DACPACs as well as the original tSQLt.class.sql script. Note: Unlike the original tSQLt.class.sql script, DACPACs are SQL Server version specific. +2. tSQLt.FriendlySQLServerVersion function reports the SQL Server Version as a string with commonly used moniker e.g. 2008R2 or 2019. +3. tSQLt is now certified for SQL Server on Linux. + +MISCELLANEOUS: + +1. Created GitHub Action for building and testing tSQLt on MSSQL 2017 and 2019 using Redgate Spawn. +2. Refactored Azure DevOps Pipeline to use more powerful VMs and azcli to create the SQLVM with a bicep file. +3. Migrated parts of the tSQLt build from ant to PowerShell. +4. Prototyped using AKS (Azure Kubernetes Service) to host MSSQL 2014, 2016, 2017, and 2019. +5. Prototyped Facade dacpacs for use in Visual Studio when developing tests with tSQLt. Ultimately we chose a full tSQLt dacpac for this work, but continue to retain the original Facade code and tests. + + +--------------------------- +Release: V1.0.7682.21917 + +BUG FIXES: + +1. Fix sysname casing for case-sensitive databases. Fixed by Trygve Wastvedt (https://github.com/twastvedt). + +2. Fixed issue in tSQLt.Private_GetFullTypeName not handling fractional seconds precision on date and time types. Fixed by saperry (https://github.com/saperry). + +NEW FEATURES: + +1. FakeFunction now accepts non-functions as data sources for example tables or SELECT statements. Contributed by Dmitrij Kultasev (https://github.com/dkultasev). + +MISCELLANEOUS: + +1. For tSQLt contributors: allow SQL Server Authentication for build + +--------------------------- +Release: V1.0.7597.5637 + +BUG FIXES: + +N/A + +NEW FEATURES: + +1. The tSQLt CLR is now signed with a new key: + + Public key (hash algorithm: sha1): + 0024000004800000940000000602000000240000525341310004000001000100b9af416ad8dfed + ec08a5652fa257f1242bf4ed60ef5a7b84a429604d62c919c5663a9c7710a7c5df9953b69ec89f + ce85d71e051140b273f4c9bf890a2bc19c48f22d7b1f1d739f90eebc5729555f7f8b63ed088bbb + 083b336f7e38b92d44cfe1c842f09632b85114772ff2122bc638c78d497c4e88c2d656c166050d + 6e1ef394 + + Public key token is e8fff6f136d7b53e + +2. Several improvements to the build process, including switching from NAnt to Ant + +3. New prepare server process (this fixes all installation issues with 2017 and 2019) + + Before installing tSQLt, you can now run the PrepareServer.sql that is part of the tSQLt.zip download. + It automatically enables CLR and installs a server certificate that allows the installation of the CLR. + There is no need to disable strict CLR security on the server nor do you need to modify database security settings. + Executing the script requires SA permissions, but needs to be done only once per server. + + Reminder: If you are using the tSQLt.NewConnection feature, + you need to execute tSQLt.EnableExternalAccess after each installation of tSQLt. + +4. Annotations + + tSQLt now allows for test case annotations to modify test behavior. The annotations implemented so far are: + + --[@tSQLt:MaxSqlMajorVersion](@MaxVersion) <-- Skips the test if the major version of SQL Server is > @MaxVersion + --[@tSQLt:MinSqlMajorVersion](@MinVersion) <-- Skips the test if the major version of SQL Server is < @MinVersion + --[@tSQLt:Skip](@SkipReason) <-- Skips the test and reports @SkipReason as reason in the output + +5. Implemented a CI pipeline for tSQLt itself in Azure DevOps + +--------------------------- +Release: V1.0.5873.27393 + +BUG FIXES: + +1. Fixed error message in tSQLt.FakeTable + +2. tSQLt.DropClass now handles already quoted names correctly + +NEW FEATURES: + +1. The tSQLt CLR is now signed with a new key: + Public Key Token = 0x7722217d36028e4c + Public Key: 0x0602000000240000525341310004000001000100F7D9A45F2B508C2887A8794B053CE5DEB28743B7C748FF545F1F51218B684454B785054629C1417D1D3542B095D80BA171294948FCF978A502AA03240C024746B563BC29B4D8DCD6956593C0C425446021D699EF6FB4DC2155DE7E393150AD6617EDC01216EA93FCE5F8F7BE9FF605AD2B8344E8CC01BEDB924ED06FD368D1D0 + The password required to sign an assembly with this key is no longer part of the code + base. This was necessary to be able to provide a secure method of installing tSQLt not + requiring the database to be set to TRUSTWORTHY anymore. + +2. tSQLt.Info() now returns the public key token of the assembly's signing key in + the CLRSigningKey column + +3. tSQLt.RunNew executes all tests in test classes (schemata) that were created with + tSQLt.NewTestClass after the last call to tSQLt.Reset + +4. tSQLt.InstallExternalAccessKey installs the required objects in the master database + to allow tSQLt to execute with EXTERNAL_ACCESS without the database being TRUSTWORTHY + +5. tSQLt.RemoveExternalAccessKey removes those objects from the master database + +6. tSQLt.EnableExternalAccess can be used to manually enable and disable EXTERNAL_ACCESS + +7. tSQLt automatically tries to enable EXTERNAL_ACCESS, each time any "run" method is called. + Enabling EXTERNAL_ACCESS is possible when either the database is TRUSTWORTHY and owned + by a server principal with EXTERNAL_ACCESS_ASSEMBLY permission, or if + tSQLt.InstallExternalAccessKey has been executed before on the server. + + This feature establishes backward compatibillity but comes at a performance cost. + It might therefore be removed in a future version. + +8. tSQLt detects at the beginning of each execution, if the requirements to enable + EXTERNAL_ACCESS are not any longer fulfilled. If the assembly is still marked as + EXTERNAL_ACCESS, the execution is halted immediately, and an error is reported + back to the caller. + +9. tSQLt checks at the beginning of each execution, if the installed assembly's version + matches the version of the T-SQL code. If a mismatch is detected, the execution is + immediately halted and an error is reported back to the caller. + +A. tSQLt.Run now allows a test result formatter to be passed in in the @TestResultFormatter + parameter. If that parameter is omitted or NULL, the default result formatter is used. + +OTHER: + +1. Cleaned up several procedures and tests + +2. Removed extraneous DROP statements from tSQLt install file. + +--------------------------- +Release: V1.0.5793.20044 + +BUG FIXES: +1. AssertEqualsTableSchema now handles gaps in column_id values correctly (thanks Greg L.) +2. Fixed handling of empty messages in AssertEmptyTable + +NEW FEATURES: +1. AssertStringIn asserts that a string value is element of a set of string values +2. ApplyConstraint can now apply cascading actions on foreign keys +3. FakeTable can now fake synonyms of tables and view (in the same database only, for now) + +OTHER: + +--------------------------- +Release: V1.0.5686.18945 + +BUG FIXES: +1. The XML output now validates against the JUnit test result XML schema at + https://raw.githubusercontent.com/windyroad/JUnit-Schema/master/JUnit.xsd + While there is no "official" JUnit schema, the above is the one that is + referenced most often online. + +2. tSQLt.DropClass now handles XML schemata correctly. + +3. All tSQLt assertions can now be called with a @Message parameter. In case of a + failure, the value of that parameter will be output before the default failure + message. + For backward compatibility, tSQLt.AssertEqualsTable still has a @FailMsg + parameter. Its use is now deprecated. + +NEW FEATURES: +1. tSQLt.Info() now returns the version and build of the SQL Server Instance it is installed on: + + SELECT * FROM tSQLt.Info() AS I; + + Version ClrVersion SqlVersion SqlBuild + -------------- -------------- ---------- -------- + 1.0.5479.30419 1.0.5479.30419 12.00 4213.00 + +2. Verbose execution mode + Executing EXEC tSQLt.SetVerbose @Verbose = 1; before running the tests will cause + tSQLt to output the test name at the beginning and the end of each test's execution. + That makes it easier in large test suites to find the output of a particular test. + +3. tSQLt.RunC + The new procedure tSQLt.RunC behaves identical to tSQLt.Run. However, instead of + expecting the test (class) name in a parameter, it parses the INPUTBUFFER and + extracts the name from a specially formed comment: + + EXEC tSQLt.RunC;--Run_Methods_Tests.[test tSQLt.RunC calls tSQLt.Run with everything after ;-- as @TestName] + + This makes for a more powerful SQL Query shortcut in SSMS as test names now do not have to be quoted anymore. + +4. tSQLt.AssertEqualsTableSchema + tSQLt.AssertEqualsTableSchema is called like tSQLt.AssertEqualsTable. Instead of + the table contents, it compares the columns including name, datatype, collation, + NULL-ability and identity property. + +5. The test runner now captures start and end time for each test. This information + is included in the XML output. The default output contains the execution duration + for each test. + +6. Both tSQLt.SpyProcedure and tSQLt.FakeFunction now handle table type parameters. + The content of a table type parameter in a spied procedure is converted into + XML and included in the _SpyProcedureLog table. + +OTHER: + +1. Farewell Sourceforge + Because of several issues over the last months and because of even more complaints + about Sourceforge's business practices by tSQLt users, we decided to find a more appropriate space. + The official downloads are now available directly on tSQLt.org. The source code + repository will find its new home either on github or bitbucket over the next few days. + +2. The fail message of tSQLt.AssertEqualsString is now broken into two lines + with aligned string values for easier comparison. + +3. The installation script now prints a welcome message. + + + +--------------------------- +Release: V1.0.5325.27056 + +BUG FIXES: +1. FakeTable now handles CHAR UDTs + +NEW FEATURES: +1. SQL 2014 now officially supported +2. tSQLt.ApplyConstraint now handles UNIQUE and PRIMARY KEY constraints +3. tSQLt.DropClass now handles UDTs +4. tSQLt.ExpectNoException can be followed by tSQLt.ExpectException +5. Added @IfExists parameter to tSQLt.RemoveObject +6. Added tSQLt.RemoveObjectIfExists +7. Added tSQLt.AssertObjectDoesNotExist + +--------------------------- +Release: V1.0.5137.39257 + +NEW FEATURES: +1. added tSQLt.RenameClass + + +--------------------------- + +Release: V1.0.5071.16906 + +NEW FEATURES: +1. added tSQLt.FakeFunction +2. added @ExpectedErrorNumber parameter to tSQLt.ExpectException + + +--------------------------- + +Release: V1.0.4969.33062 + +NEW FEATURES: +1. tSQLt.ApplyTrigger +2. tSQLt.ExpectNoException +OTHER: +1. The output of a test that errors out now contains the severity and state of that error. + +--------------------------- + +Release: V1.0.4941.23369 + +BUG FIXES: +1. tSQLt.Fail now works when transaction is in an uncommittable state. +NEW FEATURES: +1. tSQLt.AssertNotEquals +2. tSQLt.AssertEmptyTable +3. tSQLt.ExpectException +OTHER: +1. We have now a set of snippets for Red Gate SQL Prompt to support test development + Instructions of how to get them are available on our downloads page: http://tSQLt.org/downloads + +--------------------------- + +Release: V1.0.4822.19862 + +BUG FIXES: +1. Corrected defect in AssertEqualsTable where the custom error message was not being displayed. +NEW FEATURES: +1. Added tSQLt.RemoveObject procedure. + +--------------------------- + +Release: V1.0.4735.30771 + +BUG FIXES: +1. AssertEqualsTable did not quote columns. +NEW FEATURES: +1. Added AssertLike procedure. +2. Added support for multi-column foreign keys in ApplyConstraint. + +--------------------------- + +Release: V1.0.4721.29450 + +BUG FIXES: +1. When executing tSQLt.Run on an individual test, the setup procedure was sometimes not + called based on the case of the setup procedure name. +OTHER: +1. Added StubRecord procedure back in, however it is marked as 'not supported'. + +--------------------------- + +Release: V1.0.4643.26915 + +OTHER: +1. Removed unused procedure: StubRecord +2. Improved the performance of AssertEqualsTable +3. AssertEqualsTable now gives reasonalbe error messages for unsupported datatypes. More + information on unsupported datatypes is available on the documentation page for + AssertEqualsTable: http://tsqlt.org/user-guide/assertions/assertequalstable/ + +--------------------------- +Release: V1.0.4504.21220 + +BUG FIXES: +1. tSQLt.NewTestClass now does not drop schema objects if the schema is not a test class + +--------------------------- +Release: V1.0.4496.29340 + +BUG FIXES: +1. tSQLt.ResultSetFilter now supports data types introduced in SQL Server 2008 and CLR + datatypes. +2. tSLQt.AssertResultSetsHaveSameMetaData now ignores "hidden" columns. For example, + when comparing the metadata of a view, this procedure had been including underlying + columns. + +--------------------------- +Release: V1.0.4462.23207 + +NEW FEATURES: +1. tSQLt.FakeTable now supports @Defaults parameter. If @Defaults = 1 default + constraints will be preserved on columns. +2. tSQLt.FakeTable now supports @ComputedColumns parameter. If + @ComputedColumns = 1 computed columns will be preserved. + +--------------------------- + +Release: 1.0.4413.31717 + +NEW FEATURES: +1. tSQLt.Info() now reports Version and CLRVersion. These should always match! +2. tSQLt.FakeTable now supports @Identity parameter. If @Identity = 1 the + identity property of the table is preserved. + +--------------------------- + +Release: V1.0.4357.27914 + +BUG FIXES: +1. tSQLt.SpyProcedure can handle user defined types. User defined types may be in schemas and + may also be not nullable. + +NEW FEATURES: +1. SetUp can be named in any combination of upper or lower case characters (e.g. setup, SETUP, + SeTuP, etc). +--------------------------- + +Release: V1.0.4351.28410 + +BUG FIXES: +1. tSQLt.NewTestClass now handles schema names with spaces and other special characters +2. tSQLt.NewTestClass now handles if a quoted name is passed for the new schema name + +NEW FEATURES: +1. tSQLt.Uninstall removes tSQLt from the database +2. tSQLt.RunWithXmlResults executes like tSQLt.Run, but produces results is XML +3. tSQLt.TestClasses is a view that lists properties of test classes +4. tSQLt.Tests is a view that lists properties of test cases +5. Example.sql includes an example database and is referenced by the updated Quick Start + (http://tsqlt.org/quick-start) +6. tSQLt.Info() provides information about the installed version of tSQLt. + +OTHER: +1. New numbering system for the tSQLt builds. The current version is: V1.0.4351.28410 +--------------------------- + +build.12: + +BUG FIXES: +1. tSQLt.Fail now handles NULL values as parameters. +2. Corrected XmlResultFormatter to have root element of 'testsuites' instead of 'root'. +This improves compatibility with more continuous integration servers. + +NEW FEATURES: +1. FakeTable now handles a single parameter, combining the schema and table name. +This makes FakeTable more consistent with other methods in tSQLt. +2. ApplyConstraint now handles two parameters, combining the schema and table +name as the first parameter. This makes ApplyConstraint more consistent with other +methods in tSQLt. + +--------------------------- + +build.11: + +BUG FIXES: +1. ApplyConstraint for a Foreign Key that references a Faked Table is fixed. +2. SetClrEnabled.sql utlity file now handles database names with spaces. +3. Test cases whose names contain a percent sign are now displayed correctly +in the test case output. + +NEW FEATURES: +1. Warnings about renaming objects displayed when executing FakeTable or +ApplyConstraint are now hidden. +2. New method: tSQLt.SuppressOutput suppresses the console output that would +be displayed by executing a command. +3. New method: tSQLt.CaptureOutput logs the console output from executing a +command into the tSQLt.CaptureOutputLog table. + +--------------------------- + +build.10: + +BUG FIXES: +1. Standardized capitalization of table, column, procedure and function names. + +NEW FEATURES: +1. Added support for case sensitive databases. + +--------------------------- + +build.9: + +BUG FIXES: +1. When using tSQLt.Run or tSQLt.RunTestClass, if an object name on the dbo +schema had the same name as a test class, the test class could not be executed. + +2. If the output of an AssertTableEquals or the length of a test case name was +too long, an error was be produced. + +NEW FEATURES: +1. A new procedure, tSQLt.NewConnection, was added which allows statements to +be executed synchronously in a different connection context. + +--------------------------- + +build.8a: + +BUG FIXES: +1. When executing tSQLt.ResultSetFilter, if the result set metadata contained +hidden columns then those columns would be returned in the result set output. +The values of those columns would be null. Hidden columns are typically present +when the base tables of a result set contain primary keys or other constraints +which were not selected. tSQLt.ResultSetFilter has been updated to not return +the hidden columns. + +--------------------------- + +build.8: + +NEW FEATURES: +1. SpyProcedure now supports output parameters. Details are available in the +User Guide. See: http://www2.sqlity.net/tsqlt/spyprocedure + +2. The first major sections of the User Guide are now available at: +http://www.tsqlt.org - On the right hand side is a link for the User Guide. + +--------------------------- + +build.7: + +IMPORTANT: tSQLt now utilizes CLR (Common Language Runtime) stored procedures. +In order to install tSQLt, CLRs must be enabled in SQL Server. The +SetClrEnabled.sql file has the command which enables CLRs. If CLRs are not +already enabled, this command must be executed before installing tSQLt. + +NEW FEATURES: +1. A new procedure tSQLt.RunAll, executes all test classes created with the +tSQLt.NewTestClass procedure. + +2. Added procedure tSQLt.AssertResultSetsHaveSameMetaData which allows the +meta data of two result sets to be compared. This compares several properties +of each column of the result set including the column name, data type, length, +precision, scale and other properties. + +3. Added procedure tSQLt.ResultSetFilter which returns a single result set from +a statement which produces multiple result sets. For example, you want to test +a stored procedure which executes several select statements. You can now use +ResultSetFilter to choose which result set to emit, and therefore you can +capture that result set into a table for use with tSQLt.AssertEqualsTable. + +4. The results of running tests can now be output in an XML format. After +calling one of the tSQLt.Run... procedures to execute your test cases, you +can call tSQLt.XmlResultFormatter to display the results in XML. The format is +compatible with CruiseControl and can be merged into a build log the same way +that a JUnit test report is merged. diff --git a/Build/SQL/Add(tSQLt.Built)ToExampleDB.sql b/Build/SQL/Add(tSQLt.Built)ToExampleDB.sql new file mode 100644 index 000000000..145c7b594 --- /dev/null +++ b/Build/SQL/Add(tSQLt.Built)ToExampleDB.sql @@ -0,0 +1,5 @@ +GO +CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build]; +GO +ALTER ROLE db_owner ADD MEMBER [tSQLt.Build]; +GO \ No newline at end of file diff --git a/Build/ChangeDbAndExecuteStatement(tSQLt.Build).sql b/Build/SQL/ChangeDbAndExecuteStatement(tSQLt.Build).sql similarity index 100% rename from Build/ChangeDbAndExecuteStatement(tSQLt.Build).sql rename to Build/SQL/ChangeDbAndExecuteStatement(tSQLt.Build).sql diff --git a/Build/SQL/CreateBuildDbBuildOrder.txt b/Build/SQL/CreateBuildDbBuildOrder.txt new file mode 100644 index 000000000..af193f625 --- /dev/null +++ b/Build/SQL/CreateBuildDbBuildOrder.txt @@ -0,0 +1,2 @@ +ForceDropTempProcedures.sql +CreateBuildDbStub.sql \ No newline at end of file diff --git a/Build/SQL/CreateBuildDbStub.sql b/Build/SQL/CreateBuildDbStub.sql new file mode 100644 index 000000000..8b699b74c --- /dev/null +++ b/Build/SQL/CreateBuildDbStub.sql @@ -0,0 +1,12 @@ +GO +EXEC #ForceDropLogin [$(NewDbName)]; +EXEC #ForceDropDatabase [$(NewDbName)]; +GO +CREATE DATABASE [$(NewDbName)] COLLATE SQL_Latin1_General_CP1_CS_AS WITH TRUSTWORTHY OFF; +-- COLLATE SQL_Latin1_General_CP1_CS_AS +GO +CREATE LOGIN [$(NewDbName)] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B4 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; +GO +ALTER AUTHORIZATION ON DATABASE::[$(NewDbName)] TO [$(NewDbName)]; +GO +EXEC [$(NewDbName)].sys.sp_executesql N'CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build]; ALTER ROLE db_owner ADD MEMBER [tSQLt.Build];',N''; \ No newline at end of file diff --git a/Build/SQL/CreateLogin(tSQLt.Build).sql b/Build/SQL/CreateLogin(tSQLt.Build).sql new file mode 100644 index 000000000..b1fbd9a72 --- /dev/null +++ b/Build/SQL/CreateLogin(tSQLt.Build).sql @@ -0,0 +1,19 @@ +GO +SET NOCOUNT ON; +GO +USE master; +GO +EXEC #ForceDropLogin 'tSQLt.Build'; +GO +EXEC #ForceDropLogin 'tSQLt.Build.SA'; +GO +CREATE LOGIN [tSQLt.Build] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B0 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; +GO +CREATE LOGIN [tSQLt.Build.SA] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B2 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; +GO +EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt.Build.SA', @rolename = N'sysadmin' +EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt.Build', @rolename = N'dbcreator' +GO +EXEC master.sys.sp_executesql N'IF USER_ID(''tSQLt.Build'') IS NOT NULL DROP USER [tSQLt.Build];'; +EXEC master.sys.sp_executesql N'CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build];'; +GO diff --git a/Build/SQL/DisableExternalAccess.sql b/Build/SQL/DisableExternalAccess.sql new file mode 100644 index 000000000..4f05b11b2 --- /dev/null +++ b/Build/SQL/DisableExternalAccess.sql @@ -0,0 +1,4 @@ +IF(EXISTS(SELECT 1 FROM tSQLt.Info() WHERE HostPlatform NOT IN ('Linux'))) +BEGIN + EXEC tSQLt.EnableExternalAccess @try = 0, @enable=0; +END; diff --git a/Build/Drop(master.tSQLt_testutil).sql b/Build/SQL/Drop(master.tSQLt_testutil).sql similarity index 100% rename from Build/Drop(master.tSQLt_testutil).sql rename to Build/SQL/Drop(master.tSQLt_testutil).sql diff --git a/Build/Drop(tSQLtAssemblyKey)(Pre2017).sql b/Build/SQL/Drop(tSQLtAssemblyKey)(Pre2017).sql similarity index 100% rename from Build/Drop(tSQLtAssemblyKey)(Pre2017).sql rename to Build/SQL/Drop(tSQLtAssemblyKey)(Pre2017).sql diff --git a/Build/SQL/EnableExternalAccess.sql b/Build/SQL/EnableExternalAccess.sql new file mode 100644 index 000000000..2b1223f7f --- /dev/null +++ b/Build/SQL/EnableExternalAccess.sql @@ -0,0 +1,4 @@ +IF(EXISTS(SELECT 1 FROM tSQLt.Info() WHERE HostPlatform NOT IN ('Linux'))) +BEGIN + EXEC tSQLt.EnableExternalAccess @try = 0, @enable=1; +END; diff --git a/Build/ExecuteAs(tSQLt.Build).sql b/Build/SQL/ExecuteAs(tSQLt.Build).sql similarity index 100% rename from Build/ExecuteAs(tSQLt.Build).sql rename to Build/SQL/ExecuteAs(tSQLt.Build).sql diff --git a/Build/ExecuteAs(tSQLt.Build.SA).sql b/Build/SQL/ExecuteAs(tSQLt.Build.SA).sql similarity index 100% rename from Build/ExecuteAs(tSQLt.Build.SA).sql rename to Build/SQL/ExecuteAs(tSQLt.Build.SA).sql diff --git a/Build/SQL/ExecuteAsCleanup.sql b/Build/SQL/ExecuteAsCleanup.sql new file mode 100644 index 000000000..c98e6cfe2 --- /dev/null +++ b/Build/SQL/ExecuteAsCleanup.sql @@ -0,0 +1,18 @@ +GO +DECLARE @Counter INT = 0; +DECLARE @MaxAttempts INT = 10; +DECLARE @PreviousUser NVARCHAR(128) = SYSTEM_USER; + +WHILE ORIGINAL_LOGIN() <> SYSTEM_USER AND @Counter < @MaxAttempts +BEGIN + SET @Counter=@Counter+1; + REVERT; + SELECT @Counter=0,@PreviousUser=SYSTEM_USER WHERE @PreviousUser<>SYSTEM_USER; + PRINT SYSTEM_USER +END + +IF @Counter >= @MaxAttempts +BEGIN + RAISERROR('WARNING: Impersonation could not be reverted after %d attempts.', 0, 1, @MaxAttempts) WITH NOWAIT; +END +GO \ No newline at end of file diff --git a/Build/ExecuteResetValidationServer.sql b/Build/SQL/ExecuteResetValidationServer.sql similarity index 100% rename from Build/ExecuteResetValidationServer.sql rename to Build/SQL/ExecuteResetValidationServer.sql diff --git a/Build/SQL/ForceDropTempProcedures.sql b/Build/SQL/ForceDropTempProcedures.sql new file mode 100644 index 000000000..65cf63f32 --- /dev/null +++ b/Build/SQL/ForceDropTempProcedures.sql @@ -0,0 +1,55 @@ +IF OBJECT_ID('tempdb..#ForceDropDatabase') IS NOT NULL DROP PROCEDURE #ForceDropDatabase; +GO +CREATE PROCEDURE #ForceDropDatabase +@db_name NVARCHAR(MAX) +AS +BEGIN + DECLARE @cmd NVARCHAR(MAX); + IF(DB_ID(@db_name)IS NOT NULL) + BEGIN + BEGIN TRY + SET @cmd = ' + USE master; + ALTER DATABASE '+QUOTENAME(@db_name)+' SET ONLINE WITH ROLLBACK IMMEDIATE; + ALTER DATABASE '+QUOTENAME(@db_name)+' SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE; + USE '+QUOTENAME(@db_name)+'; + ALTER DATABASE '+QUOTENAME(@db_name)+' SET SINGLE_USER WITH ROLLBACK IMMEDIATE; + '; + EXEC(@cmd); + END TRY BEGIN CATCH END CATCH; + SET @cmd = ' + USE master; + DROP DATABASE '+QUOTENAME(@db_name)+'; + '; + EXEC(@cmd); + END; +END +GO +IF OBJECT_ID('tempdb..#ForceDropLogin') IS NOT NULL DROP PROCEDURE #ForceDropLogin; +GO +CREATE PROCEDURE #ForceDropLogin +@login_name NVARCHAR(MAX) +AS +BEGIN + DECLARE @cmd_dd NVARCHAR(MAX) = + ( + SELECT 'EXEC #ForceDropDatabase '+QUOTENAME(D.name,'''')+';' + FROM sys.databases AS D + JOIN sys.server_principals AS SP + ON D.owner_sid = SP.sid + WHERE SP.name = @login_name + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)'); + EXEC(@cmd_dd); + IF SUSER_SID(@login_name) IS NOT NULL + BEGIN + DECLARE @cmd_dl NVARCHAR(MAX) = ( + SELECT 'KILL '+CAST(session_id AS NVARCHAR(MAX))+';' + FROM sys.dm_exec_sessions WHERE login_name = @login_name + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)'); + SET @cmd_dl = ISNULL(@cmd_dl,'') + 'DROP LOGIN '+QUOTENAME(@login_name)+';' + EXEC(@cmd_dl); + END +END +GO diff --git a/Build/GetFailedTestCount.sql b/Build/SQL/GetFailedTestCount.sql similarity index 100% rename from Build/GetFailedTestCount.sql rename to Build/SQL/GetFailedTestCount.sql diff --git a/Build/GetFriendlySQLServerVersion.template.sql b/Build/SQL/GetFriendlySQLServerVersion.template.sql similarity index 85% rename from Build/GetFriendlySQLServerVersion.template.sql rename to Build/SQL/GetFriendlySQLServerVersion.template.sql index 454626e1f..895fc030a 100644 --- a/Build/GetFriendlySQLServerVersion.template.sql +++ b/Build/SQL/GetFriendlySQLServerVersion.template.sql @@ -9,4 +9,4 @@ DECLARE @ProductVersion NVARCHAR(128) = CAST(SERVERPROPERTY('ProductVersion') AS )SSV )X ); - PRINT @FriendlyVersion; \ No newline at end of file + SELECT @FriendlyVersion FriendlyVersion; \ No newline at end of file diff --git a/Build/GetSQLServerVersion.sql b/Build/SQL/GetSQLServerVersion.sql similarity index 100% rename from Build/GetSQLServerVersion.sql rename to Build/SQL/GetSQLServerVersion.sql diff --git a/Build/GrantBuildPermissions.sql b/Build/SQL/GrantBuildPermissions.sql similarity index 100% rename from Build/GrantBuildPermissions.sql rename to Build/SQL/GrantBuildPermissions.sql diff --git a/Build/Install(master.tSQLt_testutil).sql b/Build/SQL/Install(master.tSQLt_testutil).sql similarity index 100% rename from Build/Install(master.tSQLt_testutil).sql rename to Build/SQL/Install(master.tSQLt_testutil).sql diff --git a/Build/Install(tSQLtAssemblyKey).sql b/Build/SQL/Install(tSQLtAssemblyKey).sql similarity index 100% rename from Build/Install(tSQLtAssemblyKey).sql rename to Build/SQL/Install(tSQLtAssemblyKey).sql diff --git a/Build/PrintVersionInfo.sql b/Build/SQL/PrintVersionInfo.sql similarity index 100% rename from Build/PrintVersionInfo.sql rename to Build/SQL/PrintVersionInfo.sql diff --git a/Build/SQL/SeparatorTemplate.sql b/Build/SQL/SeparatorTemplate.sql new file mode 100644 index 000000000..4877980c5 --- /dev/null +++ b/Build/SQL/SeparatorTemplate.sql @@ -0,0 +1,4 @@ + +GO +--> /*--FILENAME--*/ +GO diff --git a/Build/SQL/UseTempDb.sql b/Build/SQL/UseTempDb.sql new file mode 100644 index 000000000..6aa4504c3 --- /dev/null +++ b/Build/SQL/UseTempDb.sql @@ -0,0 +1,3 @@ +GO +USE tempdb; +GO diff --git a/Build/SQLServerConnection.ps1 b/Build/SQLServerConnection.ps1 new file mode 100644 index 000000000..d65240772 --- /dev/null +++ b/Build/SQLServerConnection.ps1 @@ -0,0 +1,89 @@ +if (-not ([System.Management.Automation.PSTypeName]'SqlServerConnection').Type) { + + class SqlServerConnection { + hidden [string]$ServerName + hidden [string]$UserName + hidden [System.Security.SecureString]$Password + hidden [bool]$TrustedConnection + hidden [string]$ApplicationName + hidden [string]$BaseConnectionString = "Connect Timeout=60;TrustServerCertificate=true;" + + SqlServerConnection([string]$ServerName, [string]$UserName, [System.Security.SecureString]$Password,[string]$ApplicationName) { + $this.ServerName = $ServerName.Trim() + $this.UserName = $UserName.Trim() + $this.Password = $Password + $this.TrustedConnection = false + $this.ApplicationName = $ApplicationName.Trim() + } + # SqlServerConnection([string]$ServerName,[string]$ApplicationName) { + # $this.ServerName = $ServerName.Trim() + # $this.UserName = $null + # $this.Password = $null + # $this.TrustedConnection = true + # $this.ApplicationName = $ApplicationName.Trim() + # } + + [string] ToString() { + + + return @{ + ServerName= $($this.ServerName) + UserName= $($this.UserName) + Password= (ConvertFrom-SecureString $this.Password -AsPlainText) + TrustedConnection= $($this.TrustedConnection) + ApplicationName= $($this.ApplicationName) + BaseConnectionString= $($this.BaseConnectionString) + }| ConvertTo-Json -Compress + } + + static [string] ToStringStatic([SqlServerConnection]$instance) { + if ($null -eq $instance) { + return "$null" + } + else { + return $instance.ToString() + } + } + + [string] GetServerName() { + return $this.ServerName + } + + [string] GetUserName() { + return $this.UserName + } + + [System.Security.SecureString] GetPassword() { + return $this.Password + } + + [bool] GetTrustedConnection() { + return $this.TrustedConnection + } + + hidden [string] EscapeAndQuoteConnectionStringValue([string]$value) { + return "`"$( $value.Replace('"', '""') )`"" + } + + [string] GetConnectionString([string]$DatabaseName = '', [string]$ApplicationNameSuffix = '') { + $connectionString = "Server=$($this.EscapeAndQuoteConnectionStringValue($this.ServerName));" + + if ($this.TrustedConnection) { + $connectionString += "Integrated Security=SSPI;" + } else { + $connectionString += "User Id=$($this.EscapeAndQuoteConnectionStringValue($this.UserName));" + $connectionString += "Password=$($this.EscapeAndQuoteConnectionStringValue((ConvertFrom-SecureString $this.Password -AsPlainText)));" + } + if(![string]::IsNullOrWhiteSpace($DatabaseName)){ + $connectionString += "Initial Catalog=$($this.EscapeAndQuoteConnectionStringValue($DatabaseName));" + } + $PApplicationName = $this.ApplicationName; + if(![string]::IsNullOrWhiteSpace($ApplicationNameSuffix)){ + $PApplicationName+=".$ApplicationNameSuffix" + } + $connectionString += "Application Name=$($this.EscapeAndQuoteConnectionStringValue($PApplicationName));" + return $this.BaseConnectionString+$connectionString + } + } + } + \ No newline at end of file diff --git a/Build/SetupDacpacBuild.ps1 b/Build/SetupDacpacBuild.ps1 deleted file mode 100644 index 2575d517d..000000000 --- a/Build/SetupDacpacBuild.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; - -.($dir+"\CommonFunctionsAndMethods.ps1"); - -$OutputPath = $dir + "/output/DacpacBuild/"; -$TempPath = $dir + "/temp/DacpacBuild/"; - -<# Clean #> -Remove-DirectoryQuietly -Path $TempPath; -Remove-DirectoryQuietly -Path $OutputPath; - -$tempDir = New-Item -ItemType "directory" -Path $TempPath; -$outputDir = New-Item -ItemType "directory" -Path $OutputPath; - - -Expand-Archive -Path ($dir + "/output/tSQLtBuild/tSQLtFacade.zip") -DestinationPath $TempPath; -Expand-Archive -Path ($dir + "/output/tSQLtBuild/tSQLtFiles.zip") -DestinationPath $TempPath -Force; diff --git a/Build/SnInstallPfx.exe b/Build/SnInstallPfx.exe deleted file mode 100644 index a536c48e0..000000000 Binary files a/Build/SnInstallPfx.exe and /dev/null differ diff --git a/Build/Version.txt b/Build/Version.txt deleted file mode 100644 index c29253f28..000000000 --- a/Build/Version.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.7093.9172 diff --git a/Build/VersionInfo.vbs b/Build/VersionInfo.vbs deleted file mode 100644 index e3f5f862b..000000000 --- a/Build/VersionInfo.vbs +++ /dev/null @@ -1,4 +0,0 @@ -set args = WScript.Arguments -Set fso = CreateObject("Scripting.FileSystemObject") -WScript.Echo fso.GetFileVersion(args(0)) -Wscript.Quit \ No newline at end of file diff --git a/Build/buildtranslate.txt b/Build/buildtranslate.txt deleted file mode 100644 index a0eef3d68..000000000 --- a/Build/buildtranslate.txt +++ /dev/null @@ -1,8 +0,0 @@ -ant, nant -exec@executable, exec@program -exec@dir, exec@basedir, !interpreted differently -exec@outputproperty, exec@resultproperty - - -zip@destfile, zip@zipfile -fileset@file, fileset/include@name \ No newline at end of file diff --git a/Build/Import-PfxCert.ps1 b/Build/reviewneeded/Import-PfxCert.ps1 similarity index 100% rename from Build/Import-PfxCert.ps1 rename to Build/reviewneeded/Import-PfxCert.ps1 diff --git a/Build/Install the tSQLt build.docx b/Build/reviewneeded/Install the tSQLt build.docx similarity index 100% rename from Build/Install the tSQLt build.docx rename to Build/reviewneeded/Install the tSQLt build.docx diff --git a/Build/NewRelease.doc b/Build/reviewneeded/NewRelease.doc similarity index 100% rename from Build/NewRelease.doc rename to Build/reviewneeded/NewRelease.doc diff --git a/Build/Setup.bat b/Build/reviewneeded/Setup.bat similarity index 100% rename from Build/Setup.bat rename to Build/reviewneeded/Setup.bat diff --git a/Build/tSQLt.build.xml b/Build/tSQLt.build.xml deleted file mode 100644 index b7541a9da..000000000 --- a/Build/tSQLt.build.xml +++ /dev/null @@ -1,454 +0,0 @@ - - - Build tSQLt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Build/tSQLt.buildCLR.xml b/Build/tSQLt.buildCLR.xml deleted file mode 100644 index ab2fee2ba..000000000 --- a/Build/tSQLt.buildCLR.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - Build tSQLt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Build/tSQLt.experiments.build.xml b/Build/tSQLt.experiments.build.xml deleted file mode 100644 index 1b5094391..000000000 --- a/Build/tSQLt.experiments.build.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Build/tSQLt.validatebuild.xml b/Build/tSQLt.validatebuild.xml deleted file mode 100644 index 8fdea3b60..000000000 --- a/Build/tSQLt.validatebuild.xml +++ /dev/null @@ -1,745 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Build/tSQLt_Build.ps1 b/Build/tSQLt_Build.ps1 new file mode 100644 index 000000000..061c973a1 --- /dev/null +++ b/Build/tSQLt_Build.ps1 @@ -0,0 +1,143 @@ +using module "./CommonFunctionsAndMethods.psm1"; + +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +try{ + + $buildPath = $invocationDir; + $sourcePath = (Join-Path $invocationDir '../Source' | Resolve-Path); + + $OutputPath = "./output/tSQLtBuild/"; + $TempPath = "./temp/tSQLtBuild/"; + + <# Clean #> + Remove-DirectoryQuietly -Path $TempPath; + Remove-DirectoryQuietly -Path $OutputPath; + <# Init directories, capturing the return values in a variable so that they don't print. #> + $__ = New-Item -ItemType "directory" -Path $TempPath; + $__ = New-Item -ItemType "directory" -Path $OutputPath; + + Log-Output("Createting DROP CLASS statement..") + ./tSQLt_Build/CreateDropClassStatement.ps1 + + Log-Output("Copying files...") + $fileList = ("License.txt","ReleaseNotes.txt") + $fileList|ForEach-Object{(Join-Path $buildPath $_ | Resolve-Path)|Copy-Item -Destination $TempPath} + + Log-Output("Unzipping tSQLtCLR DLLs...") + Expand-Archive ./output/tSQLtCLR/tSQLtCLR.zip -DestinationPath ./temp/tSQLtBuild/tSQLtCLR + + Log-Output("Generating CREATE ASSEMBLY statement...") + $tSQLtCLRDLLPath = (Join-Path $TempPath "tSQLtCLR/tSQLtCLR.dll") | Resolve-Path + $tSQLtCLRSQLPath = (Join-Path $sourcePath "tSQLtCLR.mdl.sql") | Resolve-Path + $tSQLtCLROutputPath = (Join-Path $TempPath "CreateAssembly.sql") + ./tSQLt_Build/CreateAssemblyGenerator.ps1 $tSQLtCLROutputPath $tSQLtCLRDLLPath $tSQLtCLRSQLPath 0x000000 "0xZZZZZ" 200 "'+`n'" + + Log-Output("Generating Version.txt...") + $getAssemblyInfoPath = (Join-Path $buildPath "tSQLt_Build/GetAssemblyInfo.ps1" | Resolve-Path) + $tSQLtVersion = & $getAssemblyInfoPath $tSQLtCLRDLLPath -v + Set-Content -Path (Join-Path $tempPath "Version.txt") -Value $tSQLtVersion; + Log-Output("+------------------------------------------------------+"); + $VersionOutput = "tSQLt Version: V$tSQLtVersion".PadRight(50,' '); + Log-Output("| $VersionOutput |"); + Log-Output("+------------------------------------------------------+"); + + Log-Output("Generating GetAssemblyKeyBytes function...") + $tSQLtCLRDLLPath = (Join-Path $TempPath "tSQLtCLR/tSQLtAssemblyKey.dll") | Resolve-Path + $tSQLtCLRSQLPath = (Join-Path $sourcePath "tSQLt.Private_GetAssemblyKeyBytes.mdl.sql") | Resolve-Path + $tSQLtCLROutputPath = (Join-Path $TempPath "tSQLt.Private_GetAssemblyKeyBytes.sql") + ./tSQLt_Build/CreateAssemblyGenerator.ps1 $tSQLtCLROutputPath $tSQLtCLRDLLPath $tSQLtCLRSQLPath 0x000000 0x000001 200 "+`n0x" + + Log-Output("Generating tSQLt.class.sql file...") + $tSQLtSeparatorPath = (Join-Path $buildPath "SQL/SeparatorTemplate.sql") | Resolve-Path + $tSQLtFileListPath = (Join-Path $sourcePath "BuildOrder.txt") | Resolve-Path + $tSQLtClassOutputPath = (Join-Path $TempPath "tSQLt.class.sql") + $replacements = @( + @{"s"='$LATEST-BUILD-NUMBER$';"r"=$tSQLtVersion} + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ); + ./tSQLt_Build/ConcatenateFiles.ps1 -OutputFile $tSQLtClassOutputPath -SeparatorTemplate $tSQLtSeparatorPath -InputPath $tSQLtFileListPath -Bracket "---Build" -Replacements $replacements + + Log-Output("Updating ReleaseNotes...") + $releaseNotesPath = (Join-Path $buildPath "ReleaseNotes.txt") | Resolve-Path + (Get-Content -Path $releaseNotesPath).Replace('LATEST-BUILD-NUMBER', $tSQLtVersion) | Set-Content -Path $releaseNotesPath + + Log-Output("Creating PrepareServer.sql...") + $PrepareServerSeparatorPath = (Join-Path $buildPath "SQL/SeparatorTemplate.sql") | Resolve-Path + $PrepareServerFileListPath = (Join-Path $sourcePath "PrepareServerBuildOrder.txt") | Resolve-Path + $PrepareServerOutputPath = (Join-Path $TempPath "PrepareServer.sql") + $PrepareServerReplacements = @( + @{'s'='tSQLt.';'r'='#';}, + @{'s'="OBJECT_ID('#";'r'="OBJECT_ID('tempdb..#";}, + @{'s'='---Build-';'r'='';}, + @{'s'='---Build+';'r'='';}, + @{'s'="(?m)^\s*--.*";'r'='';isRegex=$true;} + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;}, + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ); + ./tSQLt_Build/ConcatenateFiles.ps1 -OutputFile $PrepareServerOutputPath -SeparatorTemplate $PrepareServerSeparatorPath -InputPath $PrepareServerFileListPath -Replacements $PrepareServerReplacements + + Log-Output("Creating Example.sql...") + $ExampleSeparatorPath = (Join-Path $buildPath "SQL/SeparatorTemplate.sql") | Resolve-Path + $ExampleFileListPath = (Join-Path $buildPath "../Examples/BuildOrder.txt") | Resolve-Path + $ExampleOutputPath = (Join-Path $TempPath "Example.sql") + $ExampleReplacements = @( + @{'s'="(?m)^\s*---*$";'r'='';isRegex=$true;} + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;}, + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ); + ./tSQLt_Build/ConcatenateFiles.ps1 -OutputFile $ExampleOutputPath -SeparatorTemplate $ExampleSeparatorPath -InputPath $ExampleFileListPath -Replacements $ExampleReplacements + + Log-Output("Creating CommitId.txt...") + $CommitIdPath = (Join-Path $tempPath "CommitId.txt"); + (& git rev-parse HEAD)|Set-Content -Path $CommitIdPath; + Log-Output("+--------------------------------------------------------------------------+"); + $ComitIdOutput = ("Git Commit Id: "+(Get-Content -Path $CommitIdPath )).PadRight(70,' '); + Log-Output("| $ComitIdOutput |"); + Log-Output("+--------------------------------------------------------------------------+"); + + + + Log-Output("Creating GetFriendlySQLServerVersion.sql...") + $templateContent = Get-Content -path (Join-Path $buildPath "SQL/GetFriendlySQLServerVersion.template.sql"); + $sqlFile1Content = Get-Content -path (Join-Path $sourcePath "tSQLt.FriendlySQLServerVersion.sfn.sql"); + $sqlFile2Content = Get-Content -path (Join-Path $sourcePath "tSQLt.Private_SplitSqlVersion.sfn.sql"); + + $snip1Content = (Get-SnipContent $sqlFile1Content "/*StartSnip*/" "/*EndSnip*/"); + $snip2Content = (Get-SnipContent $sqlFile2Content "/*StartSnip*/" "/*EndSnip*/"); + + $FinalContent = (($templateContent.Replace("/*snip1content*/",$snip1Content).Replace("/*snip2content*/",$snip2Content)) -join [System.Environment]::NewLine); + Set-Content -Path (Join-Path $tempPath 'GetFriendlySQLServerVersion.sql') -Value $FinalContent; + + Log-Output("Creating CreateBuildLog.sql...") + $testUtilContent = Get-Content -path (Join-Path $buildPath "../TestUtil/tSQLt_testutil.class.sql" | Resolve-Path); + $CreateBuildLogRaw = (Get-SnipContent $testUtilContent "/*CreateBuildLogStart*/" "/*CreateBuildLogEnd*/"); + $CreateBuildLog = ($CreateBuildLogRaw -join [System.Environment]::NewLine).Replace("tSQLt_testutil.CreateBuildLog","#CreateBuildLog"); + $CreateBuildLog = ($CreateBuildLog + [System.Environment]::NewLine + "EXEC #CreateBuildLog @TableName='"+'$(BuildLogTableName)'+"';" + [System.Environment]::NewLine); + Set-Content -Path (Join-Path $tempPath 'CreateBuildLog.sql') -Value ($CreateBuildLog); + + Log-Output("Packaging tSQLt...") + $toBeZipped = @("ReleaseNotes.txt", "License.txt", "tSQLt.class.sql", "Example.sql", "PrepareServer.sql"); + $compress = @{ + CompressionLevel = "Optimal" + DestinationPath = (Join-Path $OutputPath "tSQLtFiles.zip") + } + Get-ChildItem -Path (Join-Path $tempPath "*") -Include $toBeZipped | Compress-Archive @compress + + # $toBeCopied = @("Version.txt", "tSQLt.class.sql", "CommitId.txt", "GetFriendlySQLServerVersion.sql", "CreateBuildLog.sql"); + $toBeCopied = @("Version.txt", "CommitId.txt", "tSQLt.Private_GetAssemblyKeyBytes.sql", "GetFriendlySQLServerVersion.sql", "CreateBuildLog.sql"); + $toBeCopied | ForEach-Object{(Join-Path $TempPath $_ | Resolve-Path )| Copy-Item -Destination $OutputPath;} + # Copy-Item (Join-Path $tempPath "ReleaseNotes.txt" | Resolve-Path) -Destination (Join-Path $outputPath "ReadMe.txt"); + + Log-Output("Creating tSQLt Snippets...") + & ./tSQLt_Build/PackagetSQLtSnippets.ps1 + +} +catch{ + throw +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/tSQLt_Build/ConcatenateFiles.ps1 b/Build/tSQLt_Build/ConcatenateFiles.ps1 new file mode 100644 index 000000000..1375262b6 --- /dev/null +++ b/Build/tSQLt_Build/ConcatenateFiles.ps1 @@ -0,0 +1,125 @@ +param( + [Parameter(Mandatory=$true)][string]$OutputFile, + [Parameter(Mandatory=$false)][string]$SeparatorTemplate = $null, + [Parameter(Mandatory=$false)][string[]]$SeparatorContent = $null, + [Parameter(Mandatory=$true, ValueFromPipeline)][AllowNull()]$InputPath, + [array]$replacements = @{}, + [string]$IncludePattern, + [string]$Bracket = '', + [switch]$IncludeFromStart +) + +function Get-FileContent { + param( + [string]$filePath, + [string]$bracket, + [bool]$includeFromStart, + [string[]]$separator + ) + + $include = $includeFromStart + $includeHeader = $true + $includeNameInHeader = $true + $content = @() + # Write-Host(">$bracket-n<") + + Get-Content $filePath -ErrorAction Stop| ForEach-Object { + # Write-Host("$Include::>$_<") + if ($bracket -ne '' -and $_ -eq "$bracket-h") { + $includeHeader = $false + } elseif ($bracket -ne '' -and $_ -eq "$bracket-n") { + $includeNameInHeader = $false + } elseif ($bracket -ne '' -and $_ -eq "$bracket+") { + $include = $true + } elseif ($bracket -ne '' -and $_ -eq "$bracket-") { + $include = $false + } elseif ($include) { + $content += $_ + } + } + if($includeHeader){ + $filename = "" + if($includeNameInHeader){ + $fileName = (Split-Path $file -Leaf) + } + $content = ($separator|ForEach-Object{$_.Replace("/*--FILENAME--*/",$fileName)}) + $content + } + return $content +} + +# Function to concatenate files +function Concatenate-Files { + param( + [object]$fileIterator, + [string[]]$separator, + [string]$bracket, + [bool]$includeFromStart + ) + + $output = @() + foreach ($file in $fileIterator) { + Write-Verbose("-->$file") + $fileContent = Get-FileContent -filePath $file -bracket $bracket -includeFromStart $includeFromStart -separator $separator + $output += $fileContent + } + + return $output +} + +Write-Verbose("OutputFile: $OutputFile") +Write-Verbose("SeparatorTemplate: >$SeparatorTemplate<") +Write-Verbose("Input: $InputPath") + +if([string]::IsNullOrWhiteSpace($SeparatorTemplate)){ + if($null -eq $SeparatorContent){ + $SeparatorContent = @(); + } +} +else{ + $SeparatorContent = Get-Content $SeparatorTemplate -ErrorAction Stop +} +Write-Verbose(">--Separator Template-->") +$SeparatorContent|%{Write-Verbose(">:$_")} +Write-Verbose("<--Separator Template--<") +if($Bracket -eq ''){ + $IncludeFromStart = $true; +} + +try{ + + if($null -eq $InputPath){ + Write-Verbose("scriptPath: ") + $fileIterator = @() + } + elseif($InputPath -is [System.Collections.IEnumerable]){ + Write-Verbose("scriptPath: /") + $fileIterator = $InputPath + } + elseif (Test-Path $InputPath -PathType Container) { + Write-Verbose("scriptPath: $InputPath") + $fileIterator = Get-ChildItem $InputPath -Filter $IncludePattern + } + else { + $scriptPath = (Split-Path $InputPath) + Write-Verbose("scriptPath: $scriptPath") + $fileList = Get-Content $InputPath -ErrorAction Stop + $fileIterator = $fileList | ForEach-Object { Join-Path $scriptPath $_ | Resolve-Path} + } + + $concatenatedContent = (Concatenate-Files -fileIterator $fileIterator -separator $SeparatorContent -bracket $Bracket -includeFromStart $IncludeFromStart) -join "`r`n" + $replacements|ForEach-Object{ + $sv = $_["s"] + $rv=$_["r"]; + $isRegex = $_.ContainsKey("isRegex") -and $_["isRegex"]; + Write-Verbose("Replacing >$sv< with >$rv< [regex:$isRegex]..."); + if($isRegex){ + $concatenatedContent = $concatenatedContent -replace $sv, $rv + }else{ + $concatenatedContent = $concatenatedContent.Replace($sv, $rv) + } + } + $concatenatedContent | Out-File $OutputFile +}catch{ + throw +} +# $concatenatedContent \ No newline at end of file diff --git a/Build/tSQLt_Build/CreateAssemblyGenerator.ps1 b/Build/tSQLt_Build/CreateAssemblyGenerator.ps1 new file mode 100644 index 000000000..ed5eb9caf --- /dev/null +++ b/Build/tSQLt_Build/CreateAssemblyGenerator.ps1 @@ -0,0 +1,95 @@ +using module "../CommonFunctionsAndMethods.psm1"; + +param ( + [string]$OutputPath, + [string]$DllPath, + [string]$TemplatePath, + [string]$HexPlaceholder, + [string]$ThumbprintPlaceholder, + [int]$MaxLineLength, + [string]$LineSeparator +) + +function Convert-DllToHex { + param ( + [byte[]]$Bytes, + [int]$MaxLineLength, + [string]$LineSeparator + ) + + # Convert to hex string + $hexString = ($Bytes | ForEach-Object { $_.ToString("X2") }) -join '' + + # Split hex string into lines of specified length + $hexLines = $hexString -split "(.{$MaxLineLength})" | Where-Object { $_ } + + # Join lines with separator + return ($hexLines -join $LineSeparator) +} + +function Get-AssemblyThumbprint { + param ( + [string]$DllPath + ) + + $getAssemblyInfoPath = (Join-Path $PSScriptRoot "GetAssemblyInfo.ps1" | Resolve-Path) + $token = & $getAssemblyInfoPath $DllPath -t + return $token +} + +function Replace-TemplatePlaceholders { + param ( + [string]$TemplatePath, + [string]$HexPlaceholder, + [string]$ThumbprintPlaceholder, + [string]$HexContent, + [string]$Thumbprint + ) + + $templateContent = Get-Content $TemplatePath -Raw + + # Replace placeholders + $templateContent = $templateContent -replace $ThumbprintPlaceholder, ('--TTTT--' + $ThumbprintPlaceholder + '--TTTT--') + $templateContent = $templateContent -replace $HexPlaceholder, ('0x' + $HexContent) + $templateContent = $templateContent -replace ('--TTTT--' + $ThumbprintPlaceholder + '--TTTT--'), ('0x' + $Thumbprint) + + return $templateContent +} + +if (-not (Test-Path $DllPath)) { + Write-Error "DLL not found at path: $DllPath" + return +} + +if (-not (Test-Path $TemplatePath)) { + Write-Error "Template file not found at path: $TemplatePath" + return +} + +if ($MaxLineLength -le 10) { + Write-Error "Max line length must be greater than 10" + return +} + +try { + # Read DLL file bytes + $bytes = [System.IO.File]::ReadAllBytes($DllPath) + + # Convert DLL to hex + $hexContent = Convert-DllToHex -Bytes $bytes -MaxLineLength $MaxLineLength -LineSeparator $LineSeparator + + # Get assembly thumbprint + $thumbprint = Get-AssemblyThumbprint -DllPath $DllPath + + # Replace placeholders in template + $outputContent = Replace-TemplatePlaceholders -TemplatePath $TemplatePath -HexPlaceholder $HexPlaceholder -ThumbprintPlaceholder $ThumbprintPlaceholder -HexContent $hexContent -Thumbprint $thumbprint + + # # Output to file + $outputContent | Out-File -FilePath $outputPath + + Log-Output("Output generated: $outputPath"); + # $outputContent +} +catch { + Write-Error "Error: $_" +} diff --git a/Build/tSQLt_Build/CreateDropClassStatement.ps1 b/Build/tSQLt_Build/CreateDropClassStatement.ps1 new file mode 100644 index 000000000..b57787b9c --- /dev/null +++ b/Build/tSQLt_Build/CreateDropClassStatement.ps1 @@ -0,0 +1,53 @@ +using module "../CommonFunctionsAndMethods.psm1"; +Push-Location -Path $PSScriptRoot; +try{ + $baseDir = '..'; + $buildPath = $baseDir +'/'; + $tempPath = $baseDir + '/temp/tSQLtBuild/'; + $sourcePath = $baseDir + '/../Source/'; + + Log-Output '' + + $DropClassFileContent = Get-Content -path ($sourcePath+"tSQLt.DropClass.ssp.sql"); + $GetDropItemCmdFileContent = Get-Content -path ($sourcePath+"tSQLt.Private_GetDropItemCmd.sfn.sql"); + $TemplateFileContent = Get-Content -path ($sourcePath+"tSQLt.TempDropStatement.mdl.sql"); + + $OutputFilePath = $tempPath+"TempDropClass.sql"; + + $DropClassSnip = ($DropClassFileContent | Get-SnipContent -startSnipPattern "/*SnipStart: CreateDropClassStatement.ps1*/" -endSnipPattern "/*SnipEnd: CreateDropClassStatement.ps1*/"); + $DropItemSnip = ($GetDropItemCmdFileContent | Get-SnipContent -startSnipPattern "/*SnipStart: CreateDropClassStatement.ps1*/" -endSnipPattern "/*SnipEnd: CreateDropClassStatement.ps1*/"); + $DropItemParamSnip = ($GetDropItemCmdFileContent | Get-SnipContent -startSnipPattern "/*SnipParamStart: CreateDropClassStatement.ps1*/" -endSnipPattern "/*SnipParamEnd: CreateDropClassStatement.ps1*/"); + + $VariablesString = ($DropItemParamSnip.trim() -join ' ') + + $VariableNames = (Select-String '@\S+' -input $VariablesString -AllMatches|ForEach-Object{$_.matches.Value}); + + $DISP1 = ($DropItemSnip | ForEach-Object{ + $s=$_; + for($i = 0;$i -lt $VariableNames.count;$i++){ + $s=$s -replace $VariableNames[$i], ("($"+($i+1)+")") + }; + $s; + }); + $DISP2 = $DISP1.trim() -join ' '; + + $DropItemSnipPrepared = "("+ $DISP2 + ")"; + $RawDropClassStatement = $DropClassSnip -replace 'tSQLt.Private_GetDropItemCmd\s*\(\s*([^,]*)\s*,\s*([^)]*)\s*\)',$DropItemSnipPrepared; + + $DropClassStatement = ($RawDropClassStatement.trim()|Where-Object {$_ -ne "" -and $_ -notmatch "^GO(\s.*)?"}) -join ' '; + Log-Output("OutputFilePath:$OutputFilePath") + + Set-Content -Path $OutputFilePath -Value ($TemplateFileContent.Replace("/*--DROPSTATEMENT--*/",$DropClassStatement)); + + Log-Output '' +} +finally{ + Pop-Location; +} + + <# TODO + --> this makes tSQLt.class.sql truely re-runnable + --> Test this: Empty File TempDropClass.sql file should throw an error + --> Test this: If the $tempPath does not exist, BuildHelper.exe seems to currently throw an error, but does that stop the build? + --> Test this: If the $sourcePath does not exist, BuildHelper.exe seems to currently throw an error, but does that stop the build? + #> diff --git a/Build/tSQLt_Build/GetAssemblyInfo.ps1 b/Build/tSQLt_Build/GetAssemblyInfo.ps1 new file mode 100644 index 000000000..04e031abf --- /dev/null +++ b/Build/tSQLt_Build/GetAssemblyInfo.ps1 @@ -0,0 +1,49 @@ +param( + [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] + [string]$dllPath, + [Parameter(Mandatory=$true, ParameterSetName="Version")] + [switch]$v, + [Parameter(Mandatory=$true, ParameterSetName="Key")] + [switch]$k, + [Parameter(Mandatory=$true, ParameterSetName="Token")] + [switch]$t +) + +function Get-AssemblyInfo { + param( + [string]$dllPath, + [switch]$v, + [switch]$k, + [switch]$t + ) + + try { + $assemblyName = [System.Reflection.AssemblyName]::GetAssemblyName($dllPath) + + if($v) { + return $assemblyName.Version.ToString() + } + elseif($k){ + $publicKey = $assemblyName.GetPublicKey() + if ($null -eq $publicKey -or $publicKey.Length -eq 0) { + return "" + } else { + return [BitConverter]::ToString($publicKey) -replace '-' + } + } + elseif($t){ + $publicKeyToken = $assemblyName.GetPublicKeyToken() + if ($null -eq $publicKeyToken -or $publicKeyToken.Length -eq 0) { + return "" + } else { + return [BitConverter]::ToString($publicKeyToken) -replace '-' + } + } + } catch { + Write-Error "Error processing assembly: $_" + exit 1 + } +} + +(Get-AssemblyInfo -dllPath $dllPath -v:$v -k:$k -t:$t) + diff --git a/Build/tSQLt_Build/PackagetSQLtSnippets.ps1 b/Build/tSQLt_Build/PackagetSQLtSnippets.ps1 new file mode 100644 index 000000000..f1252220c --- /dev/null +++ b/Build/tSQLt_Build/PackagetSQLtSnippets.ps1 @@ -0,0 +1,25 @@ +using module "../CommonFunctionsAndMethods.psm1"; + +$__=$__ +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +try{ + $snippetsPath = Join-Path $invocationDir '../../Snippets' | Resolve-Path; + $outputPath = Join-Path $invocationDir '../output/tSQLtBuild' |Resolve-Path; + $tempPath = Join-Path $invocationDir '../temp/tSQLtBuild/SQLPromptSnippets'; + Remove-DirectoryQuietly -Path $tempPath; + $__ = New-Item -ItemType "directory" -Path $tempPath; + + + $fileList = Get-ChildItem -path (Join-Path $snippetsPath '*') -include "*.sqlpromptsnippet","ReadMe.txt" + $fileList | Copy-Item -Destination $tempPath + + $compress = @{ + CompressionLevel = "Optimal" + DestinationPath = (Join-Path $outputPath "tSQLtSnippets(SQLPrompt).zip") + } + Get-ChildItem -Path (Join-Path $tempPath "*") | Compress-Archive @compress +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/tSQLt_BuildCLR.ps1 b/Build/tSQLt_BuildCLR.ps1 new file mode 100644 index 000000000..7acc1733a --- /dev/null +++ b/Build/tSQLt_BuildCLR.ps1 @@ -0,0 +1,34 @@ +using module "./CommonFunctionsAndMethods.psm1"; +param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $pfxFilePath , + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][securestring] $pfxPassword +) +Push-Location -Path $PSScriptRoot +Write-Verbose((Get-Location).Path) +try{ + $OutputPath = "./output/tSQLtCLR/"; + $TempPath = "./temp/tSQLtCLR/"; + + <# Clean #> + Remove-DirectoryQuietly -Path $TempPath; + Remove-DirectoryQuietly -Path $OutputPath; + Get-ChildItem -Path ("../tSQLtCLR/") -Recurse -Include bin, obj|Foreach-Object{Remove-DirectoryQuietly -Path $_} + + <# Init directories, capturing the return values in a variable so that they don't print. #> + $__=$__; + $__ = New-Item -ItemType "directory" -Path $TempPath; + $__ = New-Item -ItemType "directory" -Path $OutputPath; + + ../tSQLtCLR/Build.ps1 -pfxFilePath $pfxFilePath -pfxPassword $pfxPassword + + Get-ChildItem -Path ("../tSQLtCLR/*/bin") -Recurse -Include *.dll | Copy-Item -Destination $TempPath; + + $compress = @{ + CompressionLevel = "Optimal" + DestinationPath = $OutputPath + "/tSQLtCLR.zip" + } + Get-ChildItem -Path $TempPath | Compress-Archive @compress +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/tSQLt_BuildDacpac.ps1 b/Build/tSQLt_BuildDacpac.ps1 new file mode 100644 index 000000000..b23e6daa1 --- /dev/null +++ b/Build/tSQLt_BuildDacpac.ps1 @@ -0,0 +1,59 @@ +# using module "./CommonFunctionsAndMethods.psm1"; + +Param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DacPacDatabaseName +); +<# +Technically this should be called by a matrixed job, so that dacpacs are built for all versions (we support, like not 2005, 2008) +#> + +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +$cfam = (Join-Path $invocationDir "CommonFunctionsAndMethods.psm1" | Resolve-Path) +Write-Verbose "Attempting to load module from: $cfam" +Import-Module "$cfam" -Force +Get-Module -Name CommonFunctionsAndMethods # Verify if module is loaded + +try{ + + $OutputPath = (Join-Path $invocationDir "/output/DacpacBuild/"); + $TempPath = (Join-Path $invocationDir "/temp/DacpacBuild/"); + + <# Clean #> + Remove-DirectoryQuietly -Path $TempPath; + Remove-DirectoryQuietly -Path $OutputPath; + + $__ = New-Item -ItemType "directory" -Path $TempPath; + $__ = New-Item -ItemType "directory" -Path $OutputPath; + + Expand-Archive -Path (Join-Path $invocationDir "/output/tSQLtBuild/tSQLtFiles.zip"|Resolve-Path) -DestinationPath $TempPath -Force; + Expand-Archive -Path (Join-Path $invocationDir "/output/tSQLtTests/tSQLt.tests.zip"|Resolve-Path) -DestinationPath $TempPath -Force; + + Set-Location $TempPath; + Log-Output('Building Database') + Log-Output('-- Executing ResetValidationServer.sql') + Invoke-SqlFile -SqlServerConnection $SqlServerConnection -FileNames @('ResetValidationServer.sql'); + Log-Output('-- Executing PrepareServer.sql') + Invoke-SqlFile -SqlServerConnection $SqlServerConnection -FileNames 'PrepareServer.sql'; + Log-Output('-- Executing CreateBuildDb.sql') + Invoke-SqlFile -SqlServerConnection $SqlServerConnection -FileNames "CreateBuildDb.sql" -Database "tempdb" -AdditionalParameters @{NewDbName=$DacPacDatabaseName} -PrintSqlOutput $true; + Log-Output('-- Executing tSQLt.class.sql') + Invoke-SqlFile -SqlServerConnection $SqlServerConnection -FileNames "tSQLt.class.sql" -Database "$DacPacDatabaseName"; + Log-Output('Building DACPAC') + $FriendlySQLServerVersion = Get-FriendlySQLServerVersion -SqlServerConnection $SqlServerConnection; + $tSQLtDacpacFileName = "tSQLt."+$FriendlySQLServerVersion+".dacpac"; + $tSQLtApplicationName = "tSQLt."+$FriendlySQLServerVersion; + $tSQLtConnectionString = $SqlServerConnection.GetConnectionString($DacPacDatabaseName,"tSQLt_BuildDacpac") + & sqlpackage --roll-forward Major /a:Extract /scs:"$tSQLtConnectionString" /tf:"$tSQLtDacpacFileName" /p:DacApplicationName="$tSQLtApplicationName" /p:IgnoreExtendedProperties=true /p:DacMajorVersion=0 /p:DacMinorVersion=1 /p:ExtractUsageProperties=false + if($LASTEXITCODE -ne 0) { + throw "error during execution of dacpac " + $tSQLtDacpacFileName; + } + + Copy-Item -Path $tSQLtDacpacFileName -Destination $OutputPath; + +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/tSQLt_BuildPackage.ps1 b/Build/tSQLt_BuildPackage.ps1 new file mode 100644 index 000000000..9f2392fab --- /dev/null +++ b/Build/tSQLt_BuildPackage.ps1 @@ -0,0 +1,96 @@ +using module "./CommonFunctionsAndMethods.psm1"; + +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +try{ + + $tSQLtBuildPath = (Join-Path $invocationDir '/output/tSQLtBuild/'|Resolve-Path); + $tSQLtTestsPath = (Join-Path $invocationDir '/output/tSQLtTests/'|Resolve-Path); + $DacpacBuildPath = (Join-Path $invocationDir '/output/DacpacBuild/'|Resolve-Path); + # Write-Warning "BuildPackage Inputs:" + # Write-Warning "----------------------------------------------------------------" + # Get-ChildItem $tSQLtBuildPath -Recurse |FT; + # Write-Warning "----------------------------------------------------------------" + # Get-ChildItem $tSQLtTestsPath -Recurse |FT; + # Write-Warning "----------------------------------------------------------------" + # Get-ChildItem $DacpacBuildPath -Recurse |FT; + # Write-Warning "----------------------------------------------------------------" + + $OutputPath = (Join-Path $invocationDir "/output/tSQLt/"); + $TempPath = (Join-Path $invocationDir "/temp/tSQLt/"); + + $PublicOutputPath = (Join-Path $OutputPath "public/"); + $PublicTempPath = (Join-Path $TempPath "public/"); + $ValidationOutputPath = (Join-Path $OutputPath "validation/"); + $tSQLtDacpacPath = (Join-Path $PublicTempPath "tSQLtDacpacs/"); + $SourcePath = (Join-Path $TempPath "Source/"); + $DacpacSourcePath = (Join-Path $SourcePath "Dacpacs/"); + + $PublicOutputFiles = @( + ($PublicTempPath + "/ReadMe.txt"), + ($SourcePath + "/tSQLtSnippets(SQLPrompt).zip") + ); + $ValidationOutputFiles = @( + ($SourcePath + "/Version.txt"), + ($SourcePath + "/CommitId.txt"), + ($SourcePath + "/tSQLt.tests.zip"), + ($SourcePath + "/CreateBuildLog.sql"), + ($SourcePath + "/GetFriendlySQLServerVersion.sql") + ); + + <# Clean #> + Remove-DirectoryQuietly -Path $TempPath; + Remove-DirectoryQuietly -Path $OutputPath; + + <# Init directories, capturing the return values in a variable so that they don't print. #> + $__ = New-Item -ItemType "directory" -Path $PublicOutputPath; + $__ = New-Item -ItemType "directory" -Path $tSQLtDacpacPath; + $__ = New-Item -ItemType "directory" -Path $ValidationOutputPath; + $__ = New-Item -ItemType "directory" -Path $SourcePath; + $__ = New-Item -ItemType "directory" -Path $DacpacSourcePath; + + Log-Output("Copying source files...") + $files = @( + "$($tSQLtBuildPath)Version.txt", + "$($tSQLtBuildPath)CommitId.txt", + "$($tSQLtBuildPath)CreateBuildLog.sql", + "$($tSQLtBuildPath)GetFriendlySQLServerVersion.sql", + "$($tSQLtTestsPath)tSQLt.tests.zip", + "$($tSQLtBuildPath)tSQLtSnippets(SQLPrompt).zip", + "$($tSQLtBuildPath)tSQLtFiles.zip" + ); + $files | ForEach-Object{$_ | Copy-Item -Destination $SourcePath} + Get-ChildItem $DacpacBuildPath | Copy-Item -Destination $DacpacSourcePath + + <# Copy files to temp path #> + Expand-Archive -Path (Join-Path $SourcePath "tSQLtFiles.zip" | Resolve-Path) -DestinationPath $PublicTempPath; + # Get-ChildItem -Path ($dir + "/output/DacpacBuild/tSQLtFacade.*.dacpac") | Copy-Item -Destination $FacadeDacpacPath; + Get-ChildItem -Path $DacpacSourcePath -Filter 'tSQLt.*.dacpac' | Copy-Item -Destination $tSQLtDacpacPath; + + Copy-Item (Join-Path $PublicTempPath "ReleaseNotes.txt" | Resolve-Path) -Destination (Join-Path $PublicTempPath "ReadMe.txt"); + + # Write-Warning "BuildPackage Pre-Zip:" + # Write-Warning "----------------------------------------------------------------" + # Get-ChildItem $PublicTempPath -Recurse |FT; + # Write-Warning "----------------------------------------------------------------" + # Get-ChildItem $ValidationOutputFiles -Recurse |FT; + # Write-Warning "----------------------------------------------------------------" + + <# Create the tSQLt.zip in the public output path #> + $compress = @{ + CompressionLevel = "Optimal" + DestinationPath = $PublicOutputPath + "/tSQLt.zip" + } + Get-ChildItem -Path $PublicTempPath | Compress-Archive @compress + + <# Copy all public files into public output path #> + Copy-Item -Path $PublicOutputFiles -Destination $PublicOutputPath + + <# Copy all validation files into validation output path #> + Copy-Item -Path $ValidationOutputFiles -Destination $ValidationOutputPath + +} +finally{ + Pop-Location +} diff --git a/Build/tSQLt_BuildTests.ps1 b/Build/tSQLt_BuildTests.ps1 new file mode 100644 index 000000000..d7dbbea51 --- /dev/null +++ b/Build/tSQLt_BuildTests.ps1 @@ -0,0 +1,198 @@ +using module "./CommonFunctionsAndMethods.psm1"; + +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +try{ + + $OutputPath = (Join-Path $invocationDir "./output/tSQLtTests/"); + $TempPath = (Join-Path $invocationDir "./temp/tSQLtTests/"); + $TempCLRPath = (Join-Path $TempPath "/tSQLtCLR/"); + $PackagePath = (Join-Path $TempPath "Package/"); + $SourcePath = (Join-Path $TempPath "Source/"); + + <# Clean #> + Remove-DirectoryQuietly -Path $TempPath; + Remove-DirectoryQuietly -Path $OutputPath; + <# Init directories, capturing the return values in a variable so that they don't print. #> + $__ = $__ + $__ = New-Item -ItemType "directory" -Path $TempPath; + $__ = New-Item -ItemType "directory" -Path $SourcePath; + $__ = New-Item -ItemType "directory" -Path $PackagePath; + $__ = New-Item -ItemType "directory" -Path $OutputPath; + + Log-Output("Copying source files...") + $files = @( + "output/tSQLtCLR/tSQLtCLR.zip", + "output/tSQLtBuild/tSQLt.Private_GetAssemblyKeyBytes.sql" + ); + $files|%{(Join-Path $invocationDir $_ | Resolve-Path) | Copy-Item -Destination $SourcePath} + + Log-Output("Unzipping tSQLtCLR DLLs...") + Expand-Archive (Join-Path $SourcePath "tSQLtCLR.zip") -DestinationPath $TempCLRPath + + Log-Output("Generating CREATE ASSEMBLY statement for tSQLtTestUtilCLR...") + $tSQLtTestUtilCLRDLLPath = (Join-Path $TempCLRPath "tSQLtTestUtilCLR.dll") | Resolve-Path + $tSQLtTestUtilCLRSQLPath = (Join-Path (Get-Location) "../TestUtil/tSQLtTestUtilCLR.mdl.sql") | Resolve-Path + $tSQLtTestUtilCLROutputPath = (Join-Path $TempPath "CreateTestUtilAssembly.sql") + ./tSQLt_Build/CreateAssemblyGenerator.ps1 $tSQLtTestUtilCLROutputPath $tSQLtTestUtilCLRDLLPath $tSQLtTestUtilCLRSQLPath 0x000000 "0xZZZZZ" 20000 "+`n0x" + + Log-Output("Generating CREATE ASSEMBLY statement for UnsignedEmpty...") + $UnsignedEmptyCLRDLLPath = (Join-Path $TempCLRPath "UnsignedEmpty.dll") | Resolve-Path + $UnsignedEmptyCLRSQLPath = (Join-Path (Get-Location) "../TestUtil/GetUnsignedEmptyBytes.mdl.sql") | Resolve-Path + $UnsignedEmptyCLROutputPath = (Join-Path $TempPath "GetUnsignedEmptyBytes.sql") + ./tSQLt_Build/CreateAssemblyGenerator.ps1 $UnsignedEmptyCLROutputPath $UnsignedEmptyCLRDLLPath $UnsignedEmptyCLRSQLPath 0x000000 "0xZZZZZ" 20000 "+`n0x" + + Log-Output("Building TestUtil.sql file...") + $tSQLtSeparatorPath = (Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path + $tSQLtFileListPath = (Join-Path (Get-Location) "../TestUtil/BuildOrder.txt") | Resolve-Path + $tSQLtClassOutputPath = (Join-Path $PackagePath "TestUtil.sql") + $replacements = @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ); + ./tSQLt_Build/ConcatenateFiles.ps1 -OutputFile $tSQLtClassOutputPath -SeparatorTemplate $tSQLtSeparatorPath -InputPath $tSQLtFileListPath -Replacements $replacements + + Log-Output("Building TestUtilTests.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "TestUtilTests.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../TestUtilTests") | Resolve-Path) + IncludePattern= "tSQLt_testutil*test.class.sql" + Replacements= @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Building TestUtilTests.SA.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "TestUtilTests.SA.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../TestUtilTests") | Resolve-Path) + IncludePattern= "tSQLt_testutil*test_SA.class.sql" + Replacements= @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Building AllTests.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "AllTests.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../Tests") | Resolve-Path) + IncludePattern= "*.class.sql" + Replacements= @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Building AllTests.EXTERNAL_ACCESS.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "AllTests.EXTERNAL_ACCESS.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../Tests.EXTERNAL_ACCESS") | Resolve-Path) + IncludePattern= "*.class.sql" + Replacements= @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Building AllTests.EXTERNAL_ACCESS_KEY_EXISTS.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "AllTests.EXTERNAL_ACCESS_KEY_EXISTS.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../Tests.EXTERNAL_ACCESS_KEY_EXISTS") | Resolve-Path) + IncludePattern= "*.class.sql" + Replacements= @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Building AllTests.SA.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "AllTests.SA.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../Tests.SA") | Resolve-Path) + IncludePattern= "*.class.sql" + Replacements= @( + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Copying misc files...") + $files = @( + "../../Tests/BootStrapTest.sql", + "ExecuteAs(tSQLt.Build).sql", + "ExecuteAs(tSQLt.Build.SA).sql", + "ExecuteAsCleanup.sql" + "Drop(tSQLtAssemblyKey)(Pre2017).sql", + "Install(tSQLtAssemblyKey).sql", + "ChangeDbAndExecuteStatement(tSQLt.Build).sql", + "EnableExternalAccess.sql", + "DisableExternalAccess.sql", + "Drop(master.tSQLt_testutil).sql", + "Install(master.tSQLt_testutil).sql", + "GetFailedTestCount.sql", + "Add(tSQLt.Built)ToExampleDB.sql", + "UseTempDb.sql", + "../../Examples/TestThatExamplesAreDeployed.sql" + ); + $files|%{(Join-Path $invocationDir 'SQL' $_ | Resolve-Path) | Copy-Item -Destination $PackagePath} + + Log-Output("Building CreateBuildDb.sql file...") + $parameters = @{ + OutputFile= (Join-Path $PackagePath "CreateBuildDb.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "./SQL/CreateBuildDbBuildOrder.txt") | Resolve-Path) + Replacements= @( + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Building ResetValidationServer.sql file...") + $parameters = @{ + OutputFile= (Join-Path $TempPath "ResetValidationServer.tmp.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../Source/ResetValidationServerBuildOrder1.txt") | Resolve-Path) + Replacements= @( + @{'s'='tSQLt.';'r'='#';} + @{'s'="OBJECT_ID('#";'r'="OBJECT_ID('tempdb..#";} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + $parameters = @{ + OutputFile= (Join-Path $PackagePath "ResetValidationServer.sql") + SeparatorTemplate= ((Join-Path (Get-Location) "./SQL/SeparatorTemplate.sql") | Resolve-Path) + InputPath= ((Join-Path (Get-Location) "../Source/ResetValidationServerBuildOrder2.txt") | Resolve-Path) + Replacements= @( + @{'s'='---Build-';'r'='';} + @{'s'='---Build+';'r'='';} + @{'s'="(?m)^\s*--.*";'r'='';isRegex=$true;} + @{'s'='(?m)^(?:[\t ]*(?:\r?\n|\r))+';'r'='';isRegex=$true;} + @{'s'='(?m)^\s*GO\s*((\r?\n)\s*GO\s*)+$';'r'='GO';isRegex=$true;} + ) + } + ./tSQLt_Build/ConcatenateFiles.ps1 @parameters + + Log-Output("Packaging Test Files...") + $compress = @{ + CompressionLevel = "Optimal" + DestinationPath = (Join-Path $outputPath "tSQLt.tests.zip") + } + Get-ChildItem -Path (Join-Path $PackagePath "*") | Compress-Archive @compress + +} +finally{ + Pop-Location +} \ No newline at end of file diff --git a/Build/tSQLt_Validate.ps1 b/Build/tSQLt_Validate.ps1 new file mode 100644 index 000000000..22ff1d02b --- /dev/null +++ b/Build/tSQLt_Validate.ps1 @@ -0,0 +1,236 @@ +using module "./CommonFunctionsAndMethods.psm1"; + +Param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $MainTestDb, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DacpacTestDb, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ExampleTestDb, + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string] $LogTableName = "" +); + + +$validateStartTime = Get-Date; + +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +try{ + + if([string]::IsNullOrWhiteSpace($LogTableName)){ + $LogTableName = "tempdb.dbo.[tSQLt-MultiRunLog(" + (New-Guid) + ")]"; + } + + $OutputPath = (Join-Path $invocationDir "/output/Validate/"); + $TempPath = (Join-Path $invocationDir "/temp/Validate/"); + $tSQLtPath = (Join-Path $TempPath "/tSQLt/"); + $TestsPath = (Join-Path $TempPath "/Tests/"); + $HelperSQLPath = (Join-Path $TempPath "/Tests/"); + $ResultsPath = (Join-Path $TempPath "/Results/"); + + $tSQLtZipPath = (Join-Path $invocationDir "/output/tSQLt/public/tSQLt.zip" |Resolve-Path); + $tSQLtTestsPath = (Join-Path $invocationDir "/output/tSQLt/validation" |Resolve-Path); + + <# Clean #> + Remove-DirectoryQuietly -Path $TempPath; + Remove-DirectoryQuietly -Path $OutputPath; + + <# Init directories, capturing the return values in a variable so that they don't print. #> + $__ = New-Item -ItemType "directory" -Path $tSQLtPath; + $__ = New-Item -ItemType "directory" -Path $TestsPath; + $__ = New-Item -ItemType "directory" -Path $ResultsPath; + $__ = New-Item -ItemType "directory" -Path $OutputPath; + + <# Copy files to temp path #> + Expand-Archive -Path ($tSQLtZipPath) -DestinationPath $tSQLtPath; + Expand-Archive -Path (Join-Path $tSQLtTestsPath "tSQLt.tests.zip" | Resolve-Path) -DestinationPath $TestsPath; + @( + 'CreateBuildLog.sql' + 'GetFriendlySQLServerVersion.sql' + 'Version.txt' + 'CommitId.txt' + )|ForEach-Object{(Join-Path $tSQLtTestsPath $_ | Resolve-Path)|Copy-Item -Destination $TestsPath} + + Log-Output('Initialization...') + $tSQLtVersion = (Get-Content -path (Join-Path $TestsPath 'Version.txt' | Resolve-Path)) + $tSQLtCommitId = (Get-Content -path (Join-Path $TestsPath 'CommitId.txt' | Resolve-Path)) + $SQLVersion = Get-FriendlySQLServerVersion -SqlServerConnection $SqlServerConnection -Quiet + + $FixWidth = {param($m); return '| '+$m.PadRight(70,' ')+' |'} + Log-Output(''); + Log-Output("+--------------------------------------------------------------------------+"); + Log-Output($FixWidth.invoke("Validating tSQLt Build")); + Log-Output("+--------------------------------------------------------------------------+"); + Log-Output($FixWidth.invoke("tSQLt Version: $tSQLtVersion")); + Log-Output($FixWidth.invoke("tSQLt CommitId: $tSQLtCommitId")); + Log-Output($FixWidth.invoke("SQL Server: $ServerName")); + Log-Output($FixWidth.invoke("SQL Server Version: $SQLVersion")); + Log-Output($FixWidth.invoke("Log Table Name: $LogTableName")); + Log-Output("+--------------------------------------------------------------------------+"); + Log-Output($FixWidth.invoke("Log Table Name: $LogTableName")); + Log-Output(''); + + Log-Output('Building helper scripts...') + $FixPath={param($l);$l|ForEach-Object{Write-Warning($_); Join-Path $TestsPath $_ | Resolve-Path;}}; + $ConcatenateFiles = {param([string]$output, [string[]]$fileList) + $Parameters = @{ + OutputFile = (Join-Path $TestsPath $output) + InputPath = [string[]](& $FixPath $fileList) + } + & ./tSQLt_Build/ConcatenateFiles.ps1 @Parameters + }; + & $ConcatenateFiles "temp_executeas.sql" @( + "ExecuteAs(tSQLt.Build).sql" + # "ChangeDbAndExecuteStatement(tSQLt.Build).sql" + ) ; + & $ConcatenateFiles "temp_executeas_sa.sql" @( + "ExecuteAs(tSQLt.Build.SA).sql" + # "ChangeDbAndExecuteStatement(tSQLt.Build).sql" + ) ; + & $ConcatenateFiles "temp_executeas_caller.sql" @( + # "ExecuteAs(tSQLt.Build.SA).sql" + # "ChangeDbAndExecuteStatement(tSQLt.Build).sql" + ) ; + & $ConcatenateFiles "temp_executeas_cleanup.sql" @( + "ExecuteAsCleanup.sql" + # "ChangeDbAndExecuteStatement(tSQLt.Build).sql" + ) ; + & $ConcatenateFiles "temp_create_example.sql" @( + "../tSQLt/Example.sql", + "TestUtil.sql", + "Add(tSQLt.Built)ToExampleDB.sql", + "UseTempDb.sql" + ) ; + + Log-Output("Creating Log Table $LogTableName ...") + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Caller = $true + Files = @( + (Join-Path $TestsPath "CreateBuildLog.sql" | Resolve-Path) + ) + DatabaseName = 'tempdb' + AdditionalParameters = @{ + 'BuildLogTableName' = $LogTableName + } + } + Invoke-SQLFileOrQuery @parameters; + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + TestDbName = $MainTestDb + LogTableName = $LogTableName + TestsResultFilePrefix = 'tSQLt' + DeploySource = 'class' + SourcePath = $tSQLtPath + TestsPath = $TestsPath + ResultsPath = $ResultsPath + } + & ./tSQLt_ValidateRunAll.ps1 @parameters + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + TestDbName = $DacpacTestDb + LogTableName = $LogTableName + TestsResultFilePrefix = 'tSQLtDacPac' + DeploySource = 'dacpac' + SourcePath = $tSQLtPath + TestsPath = $TestsPath + ResultsPath = $ResultsPath + } + & ./tSQLt_ValidateRunAll.ps1 @parameters + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + TestDbName = '$null' + LogTableName = $LogTableName + TestsResultFilePrefix = '$null' + DeploySource = 'example' + SourcePath = $tSQLtPath + TestsPath = $TestsPath + ResultsPath = $ResultsPath + } + & ./tSQLt_ValidateRunAll.ps1 @parameters + + Log-Output('Create tSQLt.TestResults.zip ...') + $compress = @{ + CompressionLevel = "Optimal" + DestinationPath = $OutputPath + "/tSQLt.TestResults.zip" + } + Get-ChildItem -Path $ResultsPath | Compress-Archive @compress + + Log-Output('Summary of all tests...') + Write-Warning("+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+"); + Write-Warning("|+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+|"); + Write-Warning("|| ||"); + Write-Warning("|| Build Test Result Summary ||"); + Write-Warning("|| ||"); + Write-Warning("|+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+|"); + Write-Warning("+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+"); + Write-Warning(""); + Write-Warning("Executed on SQL Server Version $SQLVersion"); + Write-Warning(""); + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Query = "SET NOCOUNT ON;EXEC tSQLt_testutil.CheckBuildLog @TableName='$LogTableName';" + DatabaseName = $MainTestDb + PrintSqlOutput = $true + } + Invoke-SQLFileOrQuery @parameters; + + + Log-Output('Confirm All Tests executed ...') + $ExpectedTestResultFiles = ( + 'TestResults_Example.xml', + 'TestResults_tSQLt.xml', + 'TestResults_tSQLt_external_access_key_exists.xml', + 'TestResults_tSQLt_external_access.xml', + 'TestResults_tSQLt_sa.xml', + 'TestResults_tSQLt_TestUtil.xml', + 'TestResults_tSQLt_TestUtil_SA.xml', + 'TestResults_tSQLtDacPac.xml', + 'TestResults_tSQLtDacPac_external_access_key_exists.xml', + 'TestResults_tSQLtDacPac_external_access.xml', + 'TestResults_tSQLtDacPac_sa.xml', + 'TestResults_tSQLtDacPac_TestUtil.xml', + 'TestResults_tSQLtDacPac_TestUtil_SA.xml' + ) + $ActualTestResultFiles = (Get-ChildItem -Path $ResultsPath -Include "TestResults*.xml" -Recurse)|%{$_.name}; + $missingFiles = ($ExpectedTestResultFiles|Where-Object{$ActualTestResultFiles -NotContains $_}) + $superfluousFiles = ($ActualTestResultFiles|Where-Object{$ExpectedTestResultFiles -NotContains $_}) + $matchingFiles = ($ActualTestResultFiles|Where-Object{$ExpectedTestResultFiles -Contains $_}) + Log-Output("+------------------------------------------------"); + Log-Output("| Expected Test Result Files:"); + $matchingFiles|%{Log-Output("| - $_");} + Log-Output("+------------------------------------------------"); + if($missingFiles.length -gt 0){ + Log-Output("| Missing Test Result Files:"); + $missingFiles|%{Log-Output("| - $_");} + }else{ + Log-Output("| No Missing Test Result Files"); + } + Log-Output("+------------------------------------------------"); + if($superfluousFiles.length -gt 0){ + Log-Output("| Unexpected Test Result Files:") + $superfluousFiles|%{Log-Output("| - $_");} + }else{ + Log-Output("| No Unexpected Test Result Files"); + } + Log-Output("+------------------------------------------------"); + if($missingFiles.Length + $superfluousFiles.Length -gt 0){ + Write-Error("Missing or Unexpected Test Result Files!") + } +} +finally{ + Pop-Location + $validateEndTime = Get-Date; + Log-Output("------------------------------------") + Log-Output("Total Duration: $($validateEndTime-$validateStartTime)") + Log-Output("------------------------------------") +} + diff --git a/Build/tSQLt_ValidateRunAll.ps1 b/Build/tSQLt_ValidateRunAll.ps1 new file mode 100644 index 000000000..963cc6553 --- /dev/null +++ b/Build/tSQLt_ValidateRunAll.ps1 @@ -0,0 +1,191 @@ +using module "./CommonFunctionsAndMethods.psm1"; + +Param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $HelperSQLPath, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $TestDbName, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $LogTableName, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $TestsResultFilePrefix, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DeploySource, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SourcePath, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $TestsPath, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ResultsPath +); + + + +function Copy-SQLXmlToFile { + # This has been tested for up to 100MB of test results! + # (Likely there is no limit, other than the 2GB of the XML data type.) + param ( + [SqlServerConnection]$sqlServerConnection, + [string]$DatabaseName, + [string]$query, + [string]$outputFile + ) + + Add-Type -AssemblyName System.Data + + try { + $connection = New-Object System.Data.SqlClient.SqlConnection($sqlServerConnection.GetConnectionString($DatabaseName,"Copy-SQLXmlToFile")) + $connection.Open() + + $command = $connection.CreateCommand() + $command.CommandText = $query + + $dddbefore = Get-Date;Write-Warning("------->>BEFORE<<-------(tSQLt_Validate.ps1:Copy-SQLXmlToFile:ExecuteScalar[$($dddbefore|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + $result = $command.ExecuteScalar() + $dddafter = Get-Date;Write-Warning("------->>After<<-------(tSQLt_Validate.ps1:Copy-SQLXmlToFile:ExecuteScalar[$($dddafter|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + $dddafter-$dddbefore + [System.IO.File]::WriteAllText($outputFile, $result) + } + catch { + Write-Error "An error occurred: $_" + } + finally { + $connection.Close() + } +} + +Function Invoke-Tests +{ + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $HelperSQLPath, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName, + [Parameter(Mandatory=$false)][switch]$Elevated, + [Parameter(Mandatory=$true)][string] $TestSetName, + [Parameter(Mandatory=$true)][string] $RunCommand, + [Parameter(Mandatory=$true)][string] $OutputFile + ); + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $Elevated + Query = $RunCommand + DatabaseName = $DatabaseName + PrintSqlOutput = $true + } + $dddbefore = Get-Date;Write-Verbose("------->>BEFORE<<-------(tSQLt_Validate.ps1:Invoke-Tests:Invoke-SQLFileOrQuery[$($dddbefore|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + $parameters; + Invoke-SQLFileOrQuery @parameters; + $dddafter = Get-Date;Write-Verbose("------->>After<<-------(tSQLt_Validate.ps1:Invoke-Tests:Invoke-SQLFileOrQuery[$($dddafter|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + Write-Verbose("Duration: $($dddafter-$dddbefore)") + + $dddbefore = Get-Date;Write-Verbose("------->>BEFORE<<-------(tSQLt_Validate.ps1:Invoke-Tests:Copy-SQLXmlToFile[$($dddbefore|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + Copy-SQLXmlToFile $SqlServerConnection $DatabaseName "EXEC [tSQLt].[XmlResultFormatter]" $OutputFile + $dddafter = Get-Date;Write-Verbose("------->>After<<-------(tSQLt_Validate.ps1:Invoke-Tests:Copy-SQLXmlToFile[$($dddafter|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + Write-Verbose("Duration: $($dddafter-$dddbefore)") + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $DatabaseName + Query = "EXEC tSQLt_testutil.LogMultiRunResult '$TestSetName';" + } + $dddbefore = Get-Date;Write-Verbose("------->>BEFORE<<-------(tSQLt_Validate.ps1:Invoke-Tests:Invoke-SQLFileOrQuery[$($dddbefore|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + # $parameters; + Invoke-SQLFileOrQuery @parameters; + $dddafter = Get-Date;Write-Verbose("------->>After<<-------(tSQLt_Validate.ps1:Invoke-Tests:Invoke-SQLFileOrQuery[$($dddafter|Get-Date -Format "yyyy:MM:dd;HH:mm:ss.fff")])") + Write-Verbose("Duration: $($dddafter-$dddbefore)") + +} +Function Invoke-TestsFromFile +{ + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][SqlServerConnection] $SqlServerConnection, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $HelperSQLPath, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $DatabaseName, + [Parameter(Mandatory=$false)][switch]$Elevated, + [Parameter(Mandatory=$true)][string] $TestFilePath, + [Parameter(Mandatory=$true)][string] $OutputFile + ); + + $TestSetName = [System.IO.Path]::GetFileName($TestFilePath); + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $DatabaseName + Query = "EXEC tSQLt.Reset;" + } + Invoke-SQLFileOrQuery @parameters; + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Files = @($TestFilePath) + DatabaseName = $DatabaseName + } + Invoke-SQLFileOrQuery @parameters; + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $DatabaseName + Elevated = $Elevated + RunCommand = "EXEC tSQLt.SetVerbose @Verbose = 1;EXEC tSQLt.RunNew;" + OutputFile = $OutputFile + TestSetName = $TestSetName + } + Invoke-Tests @parameters; + +} + + + + + + + + +Log-Output('Reset Validation Server...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Caller = $true + Files = @( + (Join-Path $TestsPath "ResetValidationServer.sql" | Resolve-Path) + (Join-Path $SourcePath "PrepareServer.sql" | Resolve-Path) + ) + DatabaseName = 'tempdb' +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... prepare master...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "Drop(master.tSQLt_testutil).sql" | Resolve-Path) + (Join-Path $TestsPath "Install(master.tSQLt_testutil).sql" | Resolve-Path) + (Join-Path $TestsPath "Drop(tSQLtAssemblyKey)(Pre2017).sql" | Resolve-Path) + ) + DatabaseName = "tempdb" +} +Invoke-SQLFileOrQuery @parameters; + +#----------------------------------------------------------------------------# +Log-Output('Run All Tests...') +#----------------------------------------------------------------------------# + +if($DeploySource -eq "example"){ + & ./tSQLt_ValidateRunExampleTests.ps1 +}else{ + & ./tSQLt_ValidateRuntSQLtTests.ps1 +} + +Log-Output('Run All Tests... cleanup master...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "Drop(master.tSQLt_testutil).sql" | Resolve-Path) + ) + DatabaseName = "tempdb" +} +Invoke-SQLFileOrQuery @parameters; diff --git a/Build/tSQLt_ValidateRunExampleTests.ps1 b/Build/tSQLt_ValidateRunExampleTests.ps1 new file mode 100644 index 000000000..5cc7cd7ff --- /dev/null +++ b/Build/tSQLt_ValidateRunExampleTests.ps1 @@ -0,0 +1,63 @@ +# +# +# +# +# +# +# + +$TestDbName = 'tSQLt_Example'; + +Log-Output("Run All Tests... Cleanup master ...") +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "Drop(master.tSQLt_testutil).sql" | Resolve-Path) + ) + DatabaseName = "tempdb" + AdditionalParameters = @{NewDbName = $TestDbName} +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output("Run All Tests... Create Database $TestDbName and deploy example code ...") +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "temp_create_example.sql" | Resolve-Path) + ) + DatabaseName = "tempdb" + AdditionalParameters = @{NewDbName = $TestDbName} +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... Set SummaryError Off, PrepMultiRun...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Query = "EXEC tSQLt_testutil.PrepMultiRunLogTable;EXEC tSQLt.SetSummaryError @SummaryError=0;" + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... TestUtil Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + TestFilePath = (Join-Path $TestsPath "TestThatExamplesAreDeployed.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_Example.xml") +} +Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... Set SummaryError O, Capture MultiRun Results...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Query = "EXEC tSQLt.SetSummaryError @SummaryError=1;EXEC tSQLt_testutil.CheckMultiRunResults @noError=1;EXEC tSQLt_testutil.StoreBuildLog @TableName='$LogTableName',@RunGroup='AllTests_Example';" + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; diff --git a/Build/tSQLt_ValidateRuntSQLtTests.ps1 b/Build/tSQLt_ValidateRuntSQLtTests.ps1 new file mode 100644 index 000000000..de54c2288 --- /dev/null +++ b/Build/tSQLt_ValidateRuntSQLtTests.ps1 @@ -0,0 +1,180 @@ +Log-Output("Run All Tests... Create Database $TestDbName ...") +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "CreateBuildDb.sql" | Resolve-Path) + ) + DatabaseName = "tempdb" + AdditionalParameters = @{NewDbName = $TestDbName} +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... Install tSQLt...') +if($DeploySource -eq "class"){ + Log-Output('Deploying tSQLt from tSQLt.class.sql...') + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Files = @( + (Join-Path $SourcePath "tSQLt.class.sql" | Resolve-Path) + ) + DatabaseName = $TestDbName + } + Invoke-SQLFileOrQuery @parameters; +}elseif($DeploySource -eq "dacpac"){ + Log-Output('Deploying tSQLt from tSQLt DacPac...') + + $FriendlySQLServerVersion = Get-FriendlySQLServerVersion -SqlServerConnection $SqlServerConnection; + $DacpacFileName = (Join-Path $SourcePath ("tSQLtDacpacs/tSQLt."+$FriendlySQLServerVersion+".dacpac") | Resolve-Path); + $SqlConnectionString = $SqlServerConnection.GetConnectionString($TestDbName,'DeployDacpac') + & sqlpackage /a:Publish /tcs:"$SqlConnectionString" /sf:"$DacpacFileName" + if($LASTEXITCODE -ne 0) { + throw "error during deployment of dacpac " + $DacpacFileName; + } +} + +# Write-Warning('-->>------------>>--') +# Get-FriendlySQLServerVersion -SqlServerConnection $SqlServerConnection +# Write-Warning('--<<------------<<--') +Log-Output('Run All Tests... Disabling External Access...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "DisableExternalAccess.sql" | Resolve-Path) + ) + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... Run Bootstrap Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Files = @( + (Join-Path $TestsPath "BootStrapTest.sql" | Resolve-Path) + ) + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... Install TestUtil.sql...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Files = @( + (Join-Path $TestsPath "TestUtil.sql" | Resolve-Path) + ) + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... Set SummaryError Off, PrepMultiRun...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Query = "EXEC tSQLt_testutil.PrepMultiRunLogTable;EXEC tSQLt.SetSummaryError @SummaryError=0;" + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + + +Log-Output('Run All Tests... TestUtil Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + TestFilePath = (Join-Path $TestsPath "TestUtilTests.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_$TestsResultFilePrefix`_TestUtil.xml") +} +Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... TestUtil_SA Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + Elevated = $true + TestFilePath = (Join-Path $TestsPath "TestUtilTests.SA.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_$TestsResultFilePrefix`_TestUtil_SA.xml") +} +Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... tSQLt Tests...') + $parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + TestFilePath = (Join-Path $TestsPath "AllTests.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_$TestsResultFilePrefix`.xml") + } + Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... tSQLt SA Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + Elevated = $true + TestFilePath = (Join-Path $TestsPath "AllTests.SA.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_$TestsResultFilePrefix`_SA.xml") +} +Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... Installing Assembly Key (needed for 2016 only)...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "Install(tSQLtAssemblyKey).sql" | Resolve-Path) + ) + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... tSQLt EXTERNAL_ACCESS_KEY_EXISTS Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + Elevated = $true + TestFilePath = (Join-Path $TestsPath "AllTests.EXTERNAL_ACCESS_KEY_EXISTS.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_$TestsResultFilePrefix`_EXTERNAL_ACCESS_KEY_EXISTS.xml") +} +Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... Enabling External Access...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Elevated = $true + Files = @( + (Join-Path $TestsPath "EnableExternalAccess.sql" | Resolve-Path) + ) + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; + +Log-Output('Run All Tests... tSQLt EXTERNAL_ACCESS Tests...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + DatabaseName = $TestDbName + Elevated = $true + TestFilePath = (Join-Path $TestsPath "AllTests.EXTERNAL_ACCESS.sql") + OutputFile = (Join-Path $ResultsPath "TestResults_$TestsResultFilePrefix`_EXTERNAL_ACCESS.xml") +} +Invoke-TestsFromFile @parameters; + +Log-Output('Run All Tests... Set SummaryError O, Capture MultiRun Results...') +$parameters = @{ + SqlServerConnection = $SqlServerConnection + HelperSQLPath = $HelperSQLPath + Query = "EXEC tSQLt.SetSummaryError @SummaryError=1;EXEC tSQLt_testutil.CheckMultiRunResults @noError=1;EXEC tSQLt_testutil.StoreBuildLog @TableName='$LogTableName',@RunGroup='AllTests_$TestsResultFilePrefix';" + DatabaseName = $TestDbName +} +Invoke-SQLFileOrQuery @parameters; diff --git a/Build_Debug/.gitignore b/Build_Debug/.gitignore deleted file mode 100644 index 239b60b51..000000000 --- a/Build_Debug/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/*.zip -/*.sql -/*.txt -FacadeDacpacs/*.* -tSQLtDacpacs/*.* diff --git a/Build_Debug/Build_Debug.ssmssqlproj b/Build_Debug/Build_Debug.ssmssqlproj deleted file mode 100644 index d6aaf24f8..000000000 --- a/Build_Debug/Build_Debug.ssmssqlproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - AllTests.EXTERNAL_ACCESS.sql - - - - - - AllTests.EXTERNAL_ACCESS_KEY_EXISTS.sql - - - - - - AllTests.SA.sql - - - - - - AllTests.sql - - - - - - BootStrapTest.sql - - - - - - ChangeDbAndExecuteStatement(tSQLt.Build).sql - - - - - - CreateBuildDb.sql - - - - - - Drop(master.tSQLt_testutil).sql - - - - - - Drop(tSQLtAssemblyKey).sql - - - - - - EnableExternalAccess.sql - - - - - - Example.sql - - - - - - ExecuteAs(tSQLt.Build).sql - - - - - - ExecuteAs(tSQLt.Build.SA).sql - - - - - - GetFailedTestCount.sql - - - - - - GetTestResults.sql - - - - - - Install(master.tSQLt_testutil).sql - - - - - - Install(tSQLtExternalAccessKey).sql - - - - - - PrepareServer.sql - - - - - - SetClrEnabled.sql - - - - - - TestThatExamplesAreDeployed.sql - - - - - - TestUtil.sql - - - - - - tSQLt.class.sql - - - - - - - - - - License.txt - - - - - - ReadMe.txt - - - - - - ReleaseNotes.txt - - - - - - tSQLt.tests.zip - - - - - - tSQLt.zip - - - - - - tSQLtSnippets(SQLPrompt).zip - - - - - - Version.txt - - - - - \ No newline at end of file diff --git a/CI/Azure-DevOps/AZ_MainPipeline.yml b/CI/Azure-DevOps/AZ_MainPipeline.yml index 9c5c41b94..9863f621b 100644 --- a/CI/Azure-DevOps/AZ_MainPipeline.yml +++ b/CI/Azure-DevOps/AZ_MainPipeline.yml @@ -14,22 +14,34 @@ schedules: always: true pool: - vmImage: 'windows-latest' + vmImage: 'ubuntu-latest' parameters: # TODO, these don't work for scheduled pipelines, not even the defaults. Fix it. Hint: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/runtime-parameters?view=azure-devops&tabs=script#check-for-an-empty-parameter-object - name: VMMatrix type: object default: - - name: SQL2012 - SQLVersionEdition: 2012Ent - - name: SQL2014 - SQLVersionEdition: 2014 + # - name: SQL2012 + # SQLVersionEdition: 2012Ent + # - name: SQL2014 + # SQLVersionEdition: 2014 - name: SQL2016 SQLVersionEdition: 2016 - - name: SQL2017 - SQLVersionEdition: 2017 - - name: SQL2019 - SQLVersionEdition: 2019 + # - name: SQL2017 + # SQLVersionEdition: 2017 + # - name: SQL2019 + # SQLVersionEdition: 2019 + # - name: SQL2022 + # SQLVersionEdition: 2022 + # - name: SQL2017Linux + # SQLVersionEdition: 2017L + # - name: SQL2019Linux + # SQLVersionEdition: 2019L + # - name: SQL2022Linux + # SQLVersionEdition: 2022L + - name: CreateEnvOnly + displayName: Create Environment Only + default: false + type: boolean - name: VMPriority displayName: VM Priority type: string @@ -55,23 +67,29 @@ variables: - name: ARTIFACT_REPO_DIR value: 'tSQLtArtifactRepo' - name: CLR_ARTIFACT_DIR - value: $(Pipeline.Workspace)\$(TSQLT_REPO_DIR)\Build\output\CLRBuild + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLtCLR - name: TSQLTFILES_ARTIFACT_DIR - value: $(Pipeline.Workspace)\$(TSQLT_REPO_DIR)\Build\output\tSQLtBuild + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLtBuild/Artifact - name: DACPAC_ARTIFACT_DIR - value: $(Pipeline.Workspace)\$(TSQLT_REPO_DIR)\Build\output\DacpacBuild + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/DacpacBuild/Artifact - name: TSQLT_PUBLIC_ARTIFACT_DIR - value: $(Pipeline.Workspace)\$(TSQLT_REPO_DIR)\Build\output\tSQLt\public + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLt/public - name: TSQLT_VALIDATION_ARTIFACT_DIR - value: $(Pipeline.Workspace)\$(TSQLT_REPO_DIR)\Build\output\tSQLt\validation + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLt/validation - name: TSQLT_TEST_RESULTS_ARTIFACT_DIR - value: $(Pipeline.Workspace)\$(TSQLT_REPO_DIR)\Build\output\tSQLt\validation\TestResults - - name: SQLCMDPath -# value: 'C:\Program Files\Microsoft SQL Server\110\Tools\Binn' for vmImage: 'vs2017-win2016' - value: 'C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn' - - name: SQLPackagePath -# value: 'C:\Program Files\Microsoft SQL Server\150\DAC\bin' Updated to the new path on 2022-02-05 - value: 'C:\Program Files\Microsoft SQL Server\160\DAC\bin' + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLt/validation/TestResults + - name: TSQLT_BUILD_DIR + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLtBuild + - name: TSQLT_TESTS_DIR + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/tSQLtTests + - name: DACPAC_BUILD_DIR + value: $(Pipeline.Workspace)/$(TSQLT_REPO_DIR)/Build/output/DacpacBuild +# - name: SQLCMDPath +# # value: 'C:/Program Files/Microsoft SQL Server/110/Tools/Binn' for vmImage: 'vs2017-win2016' +# value: 'C:/Program Files/Microsoft SQL Server/Client SDK/ODBC/170/Tools/Binn' +# - name: SQLPackagePath +# # value: 'C:/Program Files/Microsoft SQL Server/150/DAC/bin' Updated to the new path on 2022-02-05 +# value: 'C:/Program Files/Microsoft SQL Server/160/DAC/bin' resources: repositories: @@ -82,11 +100,18 @@ resources: stages: -- stage: Create_VMs +########################################################################################################## +## CREATE VMs / Containers ## +########################################################################################################## + + +- stage: Create_Environments dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel + pool: + vmImage: 'windows-latest' jobs: - - job: Create_VM + - job: Create strategy: matrix: ${{ each version in parameters.VMMatrix }}: @@ -110,10 +135,14 @@ stages: - task: PowerShell@2 name: CreateResourceGroupName inputs: + workingDirectory: "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)" targetType: 'inline' script: | - Set-Location "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)" - .("Build/CommonFunctionsAndMethods.ps1") + $cfam = (Join-Path "./Build/" "CommonFunctionsAndMethods.psm1" | Resolve-Path) + + Write-Host "Attempting to load module from: $cfam" + Import-Module "$cfam" -Force + Get-Module -Name CommonFunctionsAndMethods # Verify if module is loaded $ResourceGroupName = ("$(NamePreFix)" + (Get-Date).tostring('yyyyMMdd') + "_" + "$(SQLVersionName)" + "_" + "$(Build.BuildId)"); Log-Output "ResourceGroupName: $ResourceGroupName"; @@ -135,47 +164,73 @@ stages: scriptType: ps scriptLocation: inlineScript inlineScript: | - Set-Location "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)" - .("Build/CommonFunctionsAndMethods.ps1") + Set-Location (Join-Path "$(Pipeline.Workspace)" "$(TSQLT_REPO_DIR)") + $cfam = (Join-Path "./Build/" "CommonFunctionsAndMethods.psm1" | Resolve-Path) + Write-Host "Attempting to load module from: $cfam" + Import-Module "$cfam" -Force + Get-Module -Name CommonFunctionsAndMethods # Verify if module is loaded $SqlPort = Get-Random -minimum $env:SQLPORTMINIMUM -maximum $env:SQLPORTMAXIMUM $SQLUserName = "$env:SQL_USER_NAME"; $SQLPwd = "$env:SQL_PASSWORD"; #TODO, randomize password, instead of taking it directly from the key vault - Log-Output '=========================================================='; - Log-Output 'Executing CreateSQLVM.ps1'; - Log-Output '=========================================================='; - $Parameters = @{ - Location="$(VMLocation)"; - Size="$(VMSize)" - ResourceGroupName="$(CreateResourceGroupName.ResourceGroupName)"; - BuildId="$(Build.BuildId)"; - VMAdminName="$env:VM_USER_NAME"; - VMAdminPwd="$env:VM_PASSWORD"; - SQLVersionEdition="$(SQLVersionEdition)"; - SQLPort="$SqlPort"; - SQLUserName="$SQLUserName"; - SQLPwd="$SQLPwd"; - VMPriority="${{ parameters.VMPriority }}"; - }; - $VMDetails = .'CI/Azure-DevOps/CreateSQLVM_azcli.ps1' @Parameters - - Log-Output '=========================================================='; - Log-Output 'Done: Executing CreateSQLVM.ps1'; - Log-Output '=========================================================='; - + if("$(SQLVersionEdition)" -like "[0-9][0-9][0-9][0-9]L"){ + $SqlPort = 1433; + $SQLUserName = 'SA' + + Log-Output '=========================================================='; + Log-Output 'Executing CreateSQLContainer.ps1'; + Log-Output '=========================================================='; + $Parameters = @{ + Location="$(VMLocation)"; + # Size="$(VMSize)" + ResourceGroupName="$(CreateResourceGroupName.ResourceGroupName)"; + BuildId="$(Build.BuildId)"; + SQLVersionEdition="$(SQLVersionEdition)"; + # SQLPort="1433"; + # SQLUserName="SA"; + SQLPwd="$SQLPwd"; + SQLCpu=3; + SQLMemory=8; + }; + $VMDetails = & 'CI/Azure-DevOps/CreateSQLContainer.ps1' @Parameters + + Log-Output '=========================================================='; + Log-Output 'Done: Executing CreateSQLContainer.ps1'; + Log-Output '=========================================================='; + }else{ + Log-Output '=========================================================='; + Log-Output 'Executing CreateSQLVM_azcli.ps1'; + Log-Output '=========================================================='; + $Parameters = @{ + Location="$(VMLocation)"; + Size="$(VMSize)" + ResourceGroupName="$(CreateResourceGroupName.ResourceGroupName)"; + BuildId="$(Build.BuildId)"; + VMAdminName="$env:VM_USER_NAME"; + VMAdminPwd="$env:VM_PASSWORD"; + SQLVersionEdition="$(SQLVersionEdition)"; + SQLPort="$SqlPort"; + SQLUserName="$SQLUserName"; + SQLPwd="$SQLPwd"; + VMPriority="${{ parameters.VMPriority }}"; + }; + $VMDetails = .'CI/Azure-DevOps/CreateSQLVM_azcli.ps1' @Parameters + + Log-Output '=========================================================='; + Log-Output 'Done: Executing CreateSQLVM_azcli.ps1'; + Log-Output '=========================================================='; + } # $SerializedVMDetails=(ConvertTo-JSON -InputObject $VMDetails -Compress); # $SerializedVMDetails; #-----------------------------------------------------------------------# - # IMPORTANT (and, you've got to be kidding me): # - # The space below is absolutely required to make the ANT Task work. # + # The space below is required to make ANT work. (Not currently in use.) # #---------------------------------------|-------------------------------# $FQDNAndPort = $VMDetails.SQLVmFQDN + ", " + $VMDetails.SQLVmPort; #---------------------------------------|-------------------------------# #-----------------------------------------------------------------------# - #TODO refactor such that the resourcegroupname is created in a previous step, so that it can be used by the delete job, even if this one is cancelled/failed. $ResourceGroupName = $VMDetails.ResourceGroupName; Write-Host "##vso[task.setvariable variable=SQLUserName;isOutput=true]$SQLUserName" Write-Host "##vso[task.setvariable variable=SQLPwd;isOutput=true]$SQLPwd" @@ -185,20 +240,63 @@ stages: # Write-Host "##vso[task.setvariable variable=SerializedVMDetails;isOutput=true]$SerializedVMDetails"; + - job: PrintSQLInfo + dependsOn: Create + strategy: + matrix: + ${{ each version in parameters.VMMatrix }}: + ${{ format('{0}', version.name) }}: + SQLVersionEdition: ${{ version.SQLVersionEdition }} + SQLVersionName: ${{ version.name }} + variables: + databaseAccessDetails: $[convertToJson(dependencies.Create.outputs)] + steps: + - checkout: none - task: PowerShell@2 - name: PrintSQLVersionInfo - env: - USER_NAME: $(tSQLt-UserForCIEnvironment-UserName) - PASSWORD: $(tSQLt-UserForCIEnvironment-Password) + name: PrintSQLInfo inputs: targetType: 'inline' script: | - $DS = Invoke-Sqlcmd -Query "SELECT SUSER_NAME() U,SYSDATETIME() T,@@VERSION V;" -ServerInstance "$(CreateSQLVMEnvironment.FQDNAndPort)" -Username "$(CreateSQLVMEnvironment.SQLUserName)" -Password "$(CreateSQLVMEnvironment.SQLPwd)" -As DataSet -TrustServerCertificate + $inputObject = @' + $(databaseAccessDetails) + '@; + $myJsonObject = ConvertFrom-JSON -InputObject $inputObject; + $SQLUserNameKey = "$(System.JobName).CreateSQLVMEnvironment.SQLUserName"; + $SQLPwdKey = "$(System.JobName).CreateSQLVMEnvironment.SQLPwd"; + $FQDNAndPortKey = "$(System.JobName).CreateSQLVMEnvironment.FQDNAndPort"; + $SQLUserName = $myJsonObject.$SQLUserNameKey; + $SQLPwd = $myJsonObject.$SQLPwdKey; + $FQDNAndPort = $myJsonObject.$FQDNAndPortKey; + + $DS = Invoke-Sqlcmd -Query "SELECT SUSER_NAME() U,SYSDATETIME() T,@@VERSION V;" -ServerInstance "$FQDNAndPort" -Username "$SQLUserName" -Password "$SQLPwd" -As DataSet -TrustServerCertificate $DS.Tables[0].Rows | %{ echo "{ $($_['U']), $($_['T']), $($_['V']) }" } + if("${{ parameters.CreateEnvOnly }}" -ieq "true"){ + Write-Host '==========================================================' -ForegroundColor Yellow; + Write-Host "Name: $(SQLVersionName)"; + Write-Host "FQDN: $FQDNAndPort"; + Write-Host "User: $SQLUserName"; + Write-Host "Pass: $SQLPwd"; + Write-Host '==========================================================' -ForegroundColor Yellow; + + Write-Warning 'This information is now public! Run the following Powershell Statement to change the password immediately!'; + + $PwdChngCommand = "`$NewPwd = -join ((40..95+97..126) | Get-Random -Count 40 | % {[char]`$_}); Write-Output `"New Password: `$NewPwd`"; Invoke-Sqlcmd -Query `"ALTER LOGIN [$SQLUserName] WITH PASSWORD = '`$NewPwd';`" -ServerInstance `"$FQDNAndPort`" -Username `"$SQLUserName`" -Password `"$SQLPwd`" -TrustServerCertificate;"; + Write-Host '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - ' -ForegroundColor Yellow; + Write-Host $PwdChngCommand + Write-Host '==========================================================' -ForegroundColor Yellow; + + } + + +########################################################################################################## +## BUILD tSQLt - PART 1 ## +########################################################################################################## + - stage: Build_tSQLt_Part1 dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel + condition: eq(${{ parameters.CreateEnvOnly }}, false) jobs: @@ -206,8 +304,8 @@ stages: timeoutInMinutes: 10 cancelTimeoutInMinutes: 2 - variables: - CertificatePath: '$(Build.Repository.LocalPath)\tsqltclr\OfficialSigningKey\tSQLtOfficialSigningKey.pfx' + # variables: + # CertificatePath: '$(Build.Repository.LocalPath)/tsqltclr/OfficialSigningKey/tSQLtOfficialSigningKey.pfx' steps: @@ -222,39 +320,27 @@ stages: KeyVaultName: 'tSQLtSigningKey' - task: PowerShell@2 - name: Install_tSQLt_OfficialSigningKey + name: CompileCLR inputs: + workingDirectory: $(Build.SourcesDirectory)/Build/ targetType: 'inline' script: | + $pfxSecretBytes = [System.Convert]::FromBase64String('$(tSQLtOfficialSigningKey-Base64)') - $pfxPath = "$(Build.SourcesDirectory)/Build/tSQLtOfficialSigningKey.pfx" - [System.IO.File]::WriteAllBytes($pfxPath, $pfxSecretBytes) - &"$(Build.SourcesDirectory)/Build/SnInstallPfx" $(Build.SourcesDirectory)/Build/tSQLtOfficialSigningKey.pfx '$(tSQLtSigningKeyPassword)' tSQLt_OfficialSigningKey + $pfxFilePath = (Join-Path "$(Build.SourcesDirectory)" "/Build/tSQLtOfficialSigningKey.pfx") + [System.IO.File]::WriteAllBytes($pfxFilePath, $pfxSecretBytes) + $pfxPassword = (ConvertTo-SecureString -String '$(tSQLtSigningKeyPassword)' -Force -AsPlainText) - - task: MSBuild@1 - displayName: 'Build solution tSQLtCLR/tSQLtCLR.sln' - inputs: - solution: tSQLtCLR/tSQLtCLR.sln - platform: 'Any CPU' - configuration: CruiseControl + & ./tSQLt_BuildCLR.ps1 -pfxFilePath $pfxFilePath -pfxPassword $pfxPassword - task: CopyFiles@2 displayName: 'Copy all dll files to the ArtifactStagingDirectory' inputs: - SourceFolder: tSQLtCLR - Contents: '*/bin/*/*.dll' - TargetFolder: '$(Build.ArtifactStagingDirectory)/tSQLtCLR' + SourceFolder: ./Build/output/tSQLtCLR + Contents: 'tSQLtCLR.zip' + TargetFolder: '$(Build.ArtifactStagingDirectory)/tSQLtCLR.zip' flattenFolders: true - - task: ArchiveFiles@2 - inputs: - rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/tSQLtCLR' - includeRootFolder: false - archiveType: 'zip' - archiveFile: '$(Build.ArtifactStagingDirectory)/tSQLtCLR.zip' - replaceExistingArchive: true - verbose: true - - task: PublishPipelineArtifact@1 name: PublishCLRArtifact inputs: @@ -274,6 +360,14 @@ stages: lfs: false path: $(TSQLT_REPO_DIR) + - task: PowerShell@2 + name: CreateArtifactDir + inputs: + workingDirectory: $(Build.SourcesDirectory)/Build/ + targetType: 'inline' + script: | + mkdir -p $(CLR_ARTIFACT_DIR) + - task: DownloadPipelineArtifact@2 inputs: buildType: 'current' @@ -281,13 +375,21 @@ stages: itemPattern: '*.zip' targetPath: '$(CLR_ARTIFACT_DIR)' - - task: Ant@1 - displayName: 'Ant -debug Build/tSQLt.build.xml' + - task: PowerShell@2 + name: Build_tSQLt inputs: - buildFile: Build/tSQLt.build.xml - options: ' -D"commit.id"="$(Build.BuildId)" ' - targets: all - publishJUnitResults: false + workingDirectory: $(Build.SourcesDirectory)/Build/ + targetType: 'inline' + script: | + & ./tSQLt_Build.ps1 + + - task: PowerShell@2 + name: Build_tSQLtTests + inputs: + workingDirectory: $(Build.SourcesDirectory)/Build/ + targetType: 'inline' + script: | + & ./tSQLt_BuildTests.ps1 - task: PowerShell@2 name: CreateArtifact @@ -295,25 +397,34 @@ stages: targetType: 'inline' failOnStderr: true script: | - $basePath = "$(Build.SourcesDirectory)\Build\output\tSQLtBuild\"; - $artifactPath = ($basePath+"Artifact\"); + $basePath = "$(Build.SourcesDirectory)/Build/output/"; + $artifactPath = '$(TSQLTFILES_ARTIFACT_DIR)'; New-Item -Path $artifactPath -ItemType directory -Force - $artifactFiles = @("ReadMe.txt","CommitId.txt","CreateBuildLog.sql","GetFriendlySQLServerVersion.sql","tSQLt.tests.zip","tSQLtFacade.zip","tSQLtFiles.zip","tSQLtSnippets(SQLPrompt).zip","Version.txt"); - Get-ChildItem -Path ($basePath + "*") -Include $artifactFiles | Copy-Item -Destination "$artifactPath"; + # $toBeCopied = @("Version.txt", "CommitId.txt", "tSQLt.Private_GetAssemblyKeyBytes.sql", "GetFriendlySQLServerVersion.sql", "CreateBuildLog.sql"); + $artifactFiles = @("Version.txt","CommitId.txt", "tSQLt.Private_GetAssemblyKeyBytes.sql", "GetFriendlySQLServerVersion.sql","CreateBuildLog.sql","tSQLtFiles.zip","tSQLtSnippets(SQLPrompt).zip"); + Get-ChildItem -Path ($basePath + "tSQLtBuild/*") -Include $artifactFiles | Copy-Item -Destination "$artifactPath"; + $artifactFiles = @("tSQLt.tests.zip"); + Get-ChildItem -Path ($basePath + "tSQLtTests/*") -Include $artifactFiles | Copy-Item -Destination "$artifactPath"; Set-Content -Path ($artifactPath+"CommitId.txt") -Value "$(Build.SourceVersion)" - task: PublishPipelineArtifact@1 name: PublishtSQLtFilesArtifact inputs: - targetPath: '$(TSQLTFILES_ARTIFACT_DIR)\Artifact' + targetPath: '$(TSQLTFILES_ARTIFACT_DIR)' artifact: 'tSQLtFilesArtifact' publishLocation: 'pipeline' + +########################################################################################################## +## BUILD tSQLt - PART 2 ## +########################################################################################################## + + - stage: Build_tSQLt_Part2 dependsOn: - Build_tSQLt_Part1 - - Create_VMs + - Create_Environments jobs: - job: Build_Dacpac @@ -325,7 +436,7 @@ stages: SQLVersionEdition: ${{ version.SQLVersionEdition }} variables: - databaseAccessDetails: $[convertToJson(stageDependencies.Create_VMs.Create_VM.outputs)] + databaseAccessDetails: $[convertToJson(stageDependencies.Create_Environments.Create.outputs)] steps: - checkout: self @@ -341,11 +452,29 @@ stages: targetPath: '$(TSQLTFILES_ARTIFACT_DIR)' - task: PowerShell@2 - name: FacadeBuildDacpac + displayName: 'Install SqlServer Module' + inputs: + pwsh: true + targetType: 'inline' + script: | + # Check if the SqlServer module is installed + $module = "SqlServer" + if (-not (Get-Module -ListAvailable -Name $module)) { + # Install the SqlServer module + Install-Module -Name $module -Scope CurrentUser -Force -AllowClobber + } + Import-Module $module + + + - task: PowerShell@2 + name: BuildDacpac inputs: + pwsh: true targetType: 'inline' script: | - Set-Location "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)" + $BuildDir = (Join-Path "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)" "Build"|Resolve-Path); + Set-Location $BuildDir; + . (Join-Path $BuildDir 'SQLServerConnection.ps1'); $inputObject = @' $(databaseAccessDetails) @@ -358,17 +487,22 @@ stages: $FQDNAndPortKey = "$(System.JobName).CreateSQLVMEnvironment.FQDNAndPort"; $SQLUserName = $myJsonObject.$SQLUserNameKey; - $SQLPwd = $myJsonObject.$SQLPwdKey; + $SQLPwd = (ConvertTo-SecureString $myJsonObject.$SQLPwdKey -AsPlainText); $FQDNAndPort = $myJsonObject.$FQDNAndPortKey; + $ApplicationName = "$(Build.DefinitionName)-$(Build.BuildId)-$(System.StageName)-$(System.JobId)" + $DatabaseName = "$(buildDatabase)_dacpac_src" + $SqlServerConnection = [SqlServerConnection]::new($FQDNAndPort,$SQLUserName,$SQLPwd,$ApplicationName); - .\Build\SetupDacpacBuild.ps1 -ErrorAction Stop - .\Build\FacadeBuildDacpac.ps1 -ErrorAction Stop -ServerName "$FQDNAndPort" -DatabaseName "$(buildDatabase)" -Login " -U $SQLUserName -P $SQLPwd" -SqlCmdPath "$(SQLCMDPath)" -SqlPackagePath "$(SQLPackagePath)" - .\Build\BuildtSQLtDacpac.ps1 -ErrorAction Stop -ServerName "$FQDNAndPort" -DatabaseName "$(buildDatabase)_dacpac_src" -Login " -U $SQLUserName -P $SQLPwd" -SqlCmdPath "$(SQLCMDPath)" -SqlPackagePath "$(SQLPackagePath)" + $__ = New-Item -ItemType "directory" -Path "./output/tSQLtTests/" + # $__ = New-Item -ItemType "directory" -Path "./output/tSQLtBuild/" + Move-Item (Join-Path '$(TSQLTFILES_ARTIFACT_DIR)' 'tSQLt.tests.zip') "./output/tSQLtTests/" + Move-Item (Join-Path '$(TSQLTFILES_ARTIFACT_DIR)' 'tSQLtFiles.zip') "./output/tSQLtBuild/" + & ./tSQLt_BuildDacpac.ps1 -SqlServerConnection $SqlServerConnection -DacPacDatabaseName $DatabaseName - task: PublishPipelineArtifact@1 name: PublishtSQLtDacpacArtifact inputs: - targetPath: '$(DACPAC_ARTIFACT_DIR)' + targetPath: '$(DACPAC_BUILD_DIR)' artifact: 'tSQLtDacpacArtifact_$(System.JobName)' publishLocation: 'pipeline' @@ -387,7 +521,7 @@ stages: inputs: buildType: 'current' artifactName: 'tSQLtFilesArtifact' - targetPath: '$(TSQLTFILES_ARTIFACT_DIR)' + targetPath: '$(Pipeline.Workspace)/tSQLtArtifactTmp' - task: DownloadPipelineArtifact@2 name: DownloadtSQLtDacpacArtifact @@ -397,15 +531,39 @@ stages: targetPath: '$(Pipeline.Workspace)/dacpacArtifactTmp' - task: PowerShell@2 - name: CopyDacpacsToOutputDir + name: CopyFilesToOutputDirs inputs: targetType: 'inline' failOnStderr: true script: | + $__ = New-Item -Path "$(TSQLT_BUILD_DIR)" -ItemType directory -Force; + $__ = New-Item -Path "$(TSQLT_TESTS_DIR)" -ItemType directory -Force; + $__ = New-Item -Path "$(DACPAC_BUILD_DIR)" -ItemType directory -Force; + + Get-ChildItem -Path "$(Pipeline.Workspace)/tSQLtArtifactTmp/" -Recurse; + + $files = @( + "$(Pipeline.Workspace)/tSQLtArtifactTmp/Version.txt", + "$(Pipeline.Workspace)/tSQLtArtifactTmp/CommitId.txt", + "$(Pipeline.Workspace)/tSQLtArtifactTmp/CreateBuildLog.sql", + "$(Pipeline.Workspace)/tSQLtArtifactTmp/GetFriendlySQLServerVersion.sql", + "$(Pipeline.Workspace)/tSQLtArtifactTmp/tSQLtSnippets(SQLPrompt).zip", + "$(Pipeline.Workspace)/tSQLtArtifactTmp/tSQLtFiles.zip" + ); + $files|%{Move-Item $_ "$(TSQLT_BUILD_DIR)"} + Move-Item (Join-Path '$(Pipeline.Workspace)/tSQLtArtifactTmp' 'tSQLt.tests.zip') "$(TSQLT_TESTS_DIR)" + Get-ChildItem -Path "$(Pipeline.Workspace)/dacpacArtifactTmp" -Filter *.dacpac -Recurse; - New-Item -Path "$(DACPAC_ARTIFACT_DIR)" -ItemType directory -Force; - Get-ChildItem -Path "$(Pipeline.Workspace)/dacpacArtifactTmp" -Filter *.dacpac -Recurse | Copy-Item -Destination "$(DACPAC_ARTIFACT_DIR)" - Get-ChildItem -Path "$(DACPAC_ARTIFACT_DIR)" -Recurse; + Get-ChildItem -Path "$(Pipeline.Workspace)/dacpacArtifactTmp" -Filter *.dacpac -Recurse | Copy-Item -Destination "$(DACPAC_BUILD_DIR)" + + Write-Host "CopyFilesToOutputDirs Results:" + Write-Host "----------------------------------------------------------------" + Get-ChildItem "$(TSQLT_BUILD_DIR)" -Recurse; + Write-Host "----------------------------------------------------------------" + Get-ChildItem "$(TSQLT_TESTS_DIR)" -Recurse; + Write-Host "----------------------------------------------------------------" + Get-ChildItem "$(DACPAC_BUILD_DIR)" -Recurse; + Write-Host "----------------------------------------------------------------" - task: PowerShell@2 name: BuildtSQLtZip @@ -413,7 +571,7 @@ stages: targetType: 'inline' script: | Set-Location "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)"; - .\Build\BuildtSQLtZip.ps1 + ./Build/tSQLt_BuildPackage.ps1 Get-ChildItem -Path "$(TSQLT_PUBLIC_ARTIFACT_DIR)" -Recurse; Get-ChildItem -Path "$(TSQLT_VALIDATION_ARTIFACT_DIR)" -Recurse; @@ -441,7 +599,7 @@ stages: script: | $CheckIfGitOk = {param($isOk);if(-not $isOk){Write-Host "##vso[task.logissue type=error]GIT Failed!";throw "GIT Failed!"}}; - Set-Location "$(Pipeline.Workspace)\$(ARTIFACT_REPO_DIR)\"; + Set-Location "$(Pipeline.Workspace)/$(ARTIFACT_REPO_DIR)/"; Write-Host ("ArtifactBranchName: {0}" -f "$(ArtifactBranchName)"); try{ git config --global user.email "$env:GITHUB_EMAIL" @@ -460,11 +618,11 @@ stages: git rm -r *.* $CheckIfGitOk.invoke($?); - New-Item -Path "$(Pipeline.Workspace)\$(ARTIFACT_REPO_DIR)\public" -ItemType directory -Force; - New-Item -Path "$(Pipeline.Workspace)\$(ARTIFACT_REPO_DIR)\validation" -ItemType directory -Force; + New-Item -Path "$(Pipeline.Workspace)/$(ARTIFACT_REPO_DIR)/public" -ItemType directory -Force; + New-Item -Path "$(Pipeline.Workspace)/$(ARTIFACT_REPO_DIR)/validation" -ItemType directory -Force; - Copy-Item -Path "$(TSQLT_PUBLIC_ARTIFACT_DIR)\*" -Destination "$(Pipeline.Workspace)\$(ARTIFACT_REPO_DIR)\public" -Recurse -Verbose - Copy-Item -Path "$(TSQLT_VALIDATION_ARTIFACT_DIR)\*" -Destination "$(Pipeline.Workspace)\$(ARTIFACT_REPO_DIR)\validation" -Recurse -Verbose + Copy-Item -Path "$(TSQLT_PUBLIC_ARTIFACT_DIR)/*" -Destination "$(Pipeline.Workspace)/$(ARTIFACT_REPO_DIR)/public" -Recurse -Verbose + Copy-Item -Path "$(TSQLT_VALIDATION_ARTIFACT_DIR)/*" -Destination "$(Pipeline.Workspace)/$(ARTIFACT_REPO_DIR)/validation" -Recurse -Verbose Get-ChildItem -Path "./public" -Recurse; Get-ChildItem -Path "./validation" -Recurse; @@ -484,11 +642,17 @@ stages: } git status + +########################################################################################################## +## VALIDATE ## +########################################################################################################## + + - stage: Validate displayName: ValidateAll dependsOn: - Build_tSQLt_Part2 - - Create_VMs + - Create_Environments jobs: @@ -500,7 +664,7 @@ stages: SQLVersionEdition: ${{ version.SQLVersionEdition }} variables: - databaseAccessDetails: $[convertToJson(stageDependencies.Create_VMs.Create_VM.outputs)] + databaseAccessDetails: $[convertToJson(stageDependencies.Create_Environments.Create.outputs)] steps: - checkout: self @@ -545,10 +709,30 @@ stages: - task: PowerShell@2 - name: SetupVariables + displayName: 'Install SqlServer Module' + inputs: + pwsh: true + targetType: 'inline' + script: | + # Check if the SqlServer module is installed + $module = "SqlServer" + if (-not (Get-Module -ListAvailable -Name $module)) { + # Install the SqlServer module + Install-Module -Name $module -Scope CurrentUser -Force -AllowClobber + } + Import-Module $module + + + - task: PowerShell@2 + name: tSQLtValidateBuild inputs: + pwsh: true targetType: 'inline' script: | + $BuildDir = (Join-Path "$(Pipeline.Workspace)/$(TSQLT_REPO_DIR)" "Build"|Resolve-Path); + Set-Location $BuildDir; + . (Join-Path $BuildDir 'SQLServerConnection.ps1'); + $inputObject = @' $(databaseAccessDetails) '@; @@ -560,32 +744,40 @@ stages: $FQDNAndPortKey = "$(System.JobName).CreateSQLVMEnvironment.FQDNAndPort"; $SQLUserName = $myJsonObject.$SQLUserNameKey; - $SQLPwd = $myJsonObject.$SQLPwdKey; + $SQLPwd = (ConvertTo-SecureString $myJsonObject.$SQLPwdKey -AsPlainText); $FQDNAndPort = $myJsonObject.$FQDNAndPortKey; - - Write-Host "##vso[task.setvariable variable=SQLUserName;isOutput=true]$SQLUserName" - Write-Host "##vso[task.setvariable variable=SQLPwd;isOutput=true]$SQLPwd" - Write-Host "##vso[task.setvariable variable=FQDNAndPort;isOutput=true]$FQDNAndPort" - - - task: CmdLine@2 - name: tSQLtValidateBuild - inputs: - script: | - cd /d $(Pipeline.Workspace)\$(TSQLT_REPO_DIR) - ECHO ON - SET SQLInstanceName=$(SetupVariables.FQDNAndPort) - SET DBName=$(buildDatabase) - SET DBLogin=-U $(SetupVariables.SQLUserName) -P $(SetupVariables.SQLPwd) - SET SQLCMDPath=$(SQLCMDPath) - SET SQLPackagePath=$(SQLPackagePath) - echo %SQLInstanceName% - echo %DBName% - echo %SQLCMDPath% - echo %SQLPackagePath% - type %0 - - Build\LocalValidateBuild.bat "." "." "%SQLCMDPath%" "%SQLInstanceName%" tSQLt_Dev " %DBLogin%" "%SQLPackagePath%" -v || goto :error - :error + $ApplicationName = "$(Build.DefinitionName)-$(Build.BuildId)-$(System.StageName)-$(System.JobId)" + $DatabaseName = "$(buildDatabase)_dacpac_src" + $SqlServerConnection = [SqlServerConnection]::new($FQDNAndPort,$SQLUserName,$SQLPwd,$ApplicationName); + + $parameters = @{ + SqlServerConnection = $SqlServerConnection + MainTestDb = 'tSQLt.TmpBuild.ValidateBuild' + DacpacTestDb = 'tSQLt.TmpBuild.ValidateDacPac' + ExampleTestDb = 'tSQLt.TmpBuild.ValidateExample' + } + + & ./tSQLt_Validate.ps1 @parameters + + # - task: CmdLine@2 + # name: tSQLtValidateBuild + # inputs: + # script: | + # cd /d $(Pipeline.Workspace)/$(TSQLT_REPO_DIR) + # ECHO ON + # SET SQLInstanceName=$(SetupVariables.FQDNAndPort) + # SET DBName=$(buildDatabase) + # SET DBLogin=-U $(SetupVariables.SQLUserName) -P $(SetupVariables.SQLPwd) + # SET SQLCMDPath=$(SQLCMDPath) + # SET SQLPackagePath=$(SQLPackagePath) + # echo %SQLInstanceName% + # echo %DBName% + # echo %SQLCMDPath% + # echo %SQLPackagePath% + # type %0 + + # Build/LocalValidateBuild.bat "." "." "%SQLCMDPath%" "%SQLInstanceName%" tSQLt_Dev " %DBLogin%" "%SQLPackagePath%" -v || goto :error + # :error - task: PublishTestResults@2 @@ -618,7 +810,7 @@ stages: $TagName = "$(SQLVersionEdition)_$(Build.BuildId)" - Set-Location "$(Pipeline.Workspace)\$(ARTIFACT_REPO_DIR)\"; + Set-Location "$(Pipeline.Workspace)/$(ARTIFACT_REPO_DIR)/"; Write-Host ("ArtifactBranchName: {0}" -f "$(ArtifactBranchName)"); try{ @@ -639,17 +831,24 @@ stages: throw "git failed. See prior errors."; } - ##--##--##--##--##--##--##--##--##--##---##--##--##--##--##--##--##--##--##--## + +########################################################################################################## +## DELETE RESOURCES ## +########################################################################################################## + - stage: Delete_Resources displayName: Delete Pipeline Resources dependsOn: - - Create_VMs + - Create_Environments - Validate - condition: always() - jobs: + condition: not(eq(${{ parameters.CreateEnvOnly }}, true)) + pool: + vmImage: 'windows-latest' + + jobs: - job: Delete_VM strategy: @@ -657,11 +856,16 @@ stages: ${{ each version in parameters.VMMatrix }}: ${{ format('{0}', version.name) }}: SQLVersionEdition: ${{ version.SQLVersionEdition }} - + variables: - databaseAccessDetails: $[convertToJson(stageDependencies.Create_VMs.Create_VM.outputs)] + databaseAccessDetails: $[convertToJson(stageDependencies.Create_Environments.Create.outputs)] steps: + - checkout: self + clean: true + lfs: false + path: $(TSQLT_REPO_DIR) + - task: AzureCLI@2 name: DeleteAzureVM inputs: @@ -670,15 +874,18 @@ stages: scriptType: ps scriptLocation: inlineScript inlineScript: | + Set-Location (Join-Path "$(Pipeline.Workspace)" "$(TSQLT_REPO_DIR)") + $cfam = (Join-Path "./Build/" "CommonFunctionsAndMethods.psm1" | Resolve-Path) + Write-Host "Attempting to load module from: $cfam" + Import-Module "$cfam" -Force + Get-Module -Name CommonFunctionsAndMethods # Verify if module is loaded + $inputObject = @' $(databaseAccessDetails) '@; $myJsonObject = ConvertFrom-JSON -InputObject $inputObject; $ResourceGroupNameKey = "$(System.JobName).CreateResourceGroupName.ResourceGroupName"; $ResourceGroupName = $myJsonObject.$ResourceGroupNameKey; - - Set-Location $(Build.Repository.LocalPath) - .("Build/CommonFunctionsAndMethods.ps1") - + $ResourceGroupName | Log-Output; az group delete --name $ResourceGroupName --yes diff --git a/CI/Azure-DevOps/CreateSQLContainer.ps1 b/CI/Azure-DevOps/CreateSQLContainer.ps1 new file mode 100644 index 000000000..b6a95919b --- /dev/null +++ b/CI/Azure-DevOps/CreateSQLContainer.ps1 @@ -0,0 +1,98 @@ +<# USAGE: ./CreateSQLContainer.ps1 -Location "East US 2" -ResourceGroupName "myTestResourceGroup" -SQLVersionEdition "2022L" -SQLPwd "aoeihag;ladjfalkj46" -BuildId "001" #> +# using module "../../Build/CommonFunctionsAndMethods.psm1"; + +Param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Location, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ResourceGroupName, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $BuildId, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SQLVersionEdition, + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SQLPwd, + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][int] $SQLCpu = 4, + [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][int] $SQLMemory = 8 +); +Write-Host "Starting execution of CreateSQLContainer.ps1" +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +$cfam = (Join-Path (Join-Path $invocationDir "../../Build/") "CommonFunctionsAndMethods.psm1" | Resolve-Path) +Write-Host "Attempting to load module from: $cfam" +Import-Module "$cfam" -Force -Verbose +Get-Module -Name CommonFunctionsAndMethods # Verify if module is loaded + +$SQLPort = 1433; +$SQLUserName = 'SA'; + +$dir = $invocationDir; +$projectDir = Split-Path (Split-Path $dir); + +Log-Output "FileLocation: ", $dir; +Log-Output "Project Location: ", $projectDir; + + +Log-Output "*---------------*"; +Log-Output (az --version|Out-String); +Log-Output (bicep --version|Out-String); +Log-Output ($psversiontable|Out-String); +Log-Output "*---------------*"; + + +Log-Output "<-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><->"; +Log-Output "<-> <->"; +Log-Output "<-> START 1 <->"; +Log-Output "<-> <->"; +Log-Output "<-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><->"; +Log-Output "Parameters:"; +Log-Output "ResourceGroupName:", $ResourceGroupName; +Log-Output "Location:", $Location; +Log-Output "BuildId:", $BuildId; +Log-Output "SQLVersionEdition:", $SQLVersionEdition; +Log-Output "SQLPort:", $SQLPort; +Log-Output "<-> END 1 <-><-><-><-><-><-><-><-><-><-><-><-><->"; + +<# FYI Usage: $SQLVersionEditionHash.$SQLVersionEdition.offer = "SQL2016SP2-WS2016" #> +$SQLVersionEditionHash = @{ + "2017L"=@{"sqlversion"="2017";"image"="mcr.microsoft.com/mssql/server:2017-latest";}; + "2019L"=@{"sqlversion"="2019";"image"="mcr.microsoft.com/mssql/server:2019-latest";} + "2022L"=@{"sqlversion"="2022";"image"="mcr.microsoft.com/mssql/server:2022-latest";} +}; + +$SQLVersionEditionInfo = $SQLVersionEditionHash.$SQLVersionEdition; +Log-Output "SQLVersionEditionInfo: ", $SQLVersionEditionInfo; +$ContainerName = ("C{0}-{1}###############" -f $BuildId,$SQLVersionEdition).substring(0,15).replace('#','').ToLower() +$ContainerImage = $SQLVersionEditionInfo.image + +Log-Output 'Creating SQL Server Container resources' + +$templatePath = (Join-Path $invocationDir 'CreateSQLContainerTemplate.bicep' | Resolve-Path); +Log-Output "*---------------*"; +Log-Output $templatePath +Log-Output "*---------------*"; + +$deploymentResult = (az deployment sub create --name $ContainerName --location $Location --template-file $templatePath --parameters location=$Location containerName=$ContainerName sqlServerImage=$ContainerImage newResourceGroupName=$ResourceGroupName saPassword=$SQLPwd cpu=$SQLCpu memory=$SQLMemory); + +Log-Output 'Done: Creating SQL Server Container' +Log-Output 'Prep SQL Server for tSQLt Build' +# $deploymentResult +$outputs = ($deploymentResult|ConvertFrom-Json).properties.outputs +$ipAddress = $outputs.ipAddress.value +$Port = $outputs.Port.value +Log-Output "*---------------*"; +Log-Output "SQL Server address: $ipAddress,$Port" +Log-Output "*---------------*"; + +$GetSQLVersionPath = (Join-Path $invocationDir 'GetSQLServerVersion.sql' | Resolve-Path); +$DS = Invoke-Sqlcmd -InputFile $GetSQLVersionPath -ServerInstance "$ipAddress,$Port" -Username "$SQLUserName" -Password "$SQLPwd" -TrustServerCertificate -As DataSet +$DS.Tables[0].Rows | ForEach-Object{ Log-Output "{ $($_['LoginName']), $($_['TimeStamp']), $($_['VersionDetail']), $($_['ProductVersion']), $($_['ProductLevel']), $($_['SqlVersion']) }" } + +$ActualSQLVersion = $DS.Tables[0].Rows[0]['SqlVersion']; +Log-Output "Actual SQL Version:",$ActualSQLVersion; + +Log-Output 'Done: Prep SQL Server for tSQLt Build'; + +Return @{ + "VmName"="$ContainerName"; + "ResourceGroupName"="$ResourceGroupName"; + "SQLVmFQDN"="$ipAddress"; ##[vmname].[region].cloudapp.azure.com + "SQLVmPort"="$SQLPort"; ##1433 + "SQLVersionEdition"="$SQLVersionEdition"; ##2012Ent +}; diff --git a/CI/Azure-DevOps/CreateSQLContainerAndIpAddressModule.bicep b/CI/Azure-DevOps/CreateSQLContainerAndIpAddressModule.bicep new file mode 100644 index 000000000..5f952f748 --- /dev/null +++ b/CI/Azure-DevOps/CreateSQLContainerAndIpAddressModule.bicep @@ -0,0 +1,59 @@ +param location string = resourceGroup().location +param containerName string +param sqlServerImage string +param cpu int +param memory int +@secure() +param saPassword string + +var containerGroupName = '${containerName}-group' +var sqlPort = 1433 + +resource containerGroup 'Microsoft.ContainerInstance/containerGroups@2021-10-01' = { + name: containerGroupName + location: location + properties: { + containers: [ + { + name: containerName + properties: { + image: sqlServerImage + resources: { + requests: { + cpu: cpu + memoryInGB: memory + } + } + environmentVariables: [ + { + name: 'ACCEPT_EULA' + value: 'Y' + } + { + name: 'MSSQL_SA_PASSWORD' + secureValue: saPassword + } + ] + ports: [ + { + port: sqlPort + } + ] + } + } + ] + osType: 'Linux' + ipAddress: { + type: 'Public' + ports: [ + { + protocol: 'tcp' + port: sqlPort + } + ] + } + } +} + +output ipAddress string = containerGroup.properties.ipAddress.ip +output Port int = containerGroup.properties.ipAddress.ports[0].port diff --git a/CI/Azure-DevOps/CreateSQLContainerTemplate.bicep b/CI/Azure-DevOps/CreateSQLContainerTemplate.bicep new file mode 100644 index 000000000..dd0798986 --- /dev/null +++ b/CI/Azure-DevOps/CreateSQLContainerTemplate.bicep @@ -0,0 +1,37 @@ +targetScope='subscription' + +param location string = 'eastus2' +param newResourceGroupName string = 'sqlserver-container-test-rg' +param containerName string = 'sqlserver2022' +param sqlServerImage string = 'mcr.microsoft.com/mssql/server:2022-latest' +@secure() +param saPassword string +param cpu int = 4 +param memory int = 8 + + +resource newResourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: newResourceGroupName + location: location + tags: { + Department: 'tSQLtCI' + Ephemeral: 'True' + } +} + + +module containers './CreateSQLContainerAndIpAddressModule.bicep' = { + name: 'deployContainers' + scope: newResourceGroup + params: { + location: location + containerName: containerName + sqlServerImage: sqlServerImage + cpu:cpu + memory:memory + saPassword: saPassword + } +} + +output ipAddress string = containers.outputs.ipAddress +output Port int = containers.outputs.Port diff --git a/CI/Azure-DevOps/CreateSQLVM_azcli.ps1 b/CI/Azure-DevOps/CreateSQLVM_azcli.ps1 index cc61a18bd..4376c65ff 100644 --- a/CI/Azure-DevOps/CreateSQLVM_azcli.ps1 +++ b/CI/Azure-DevOps/CreateSQLVM_azcli.ps1 @@ -19,15 +19,18 @@ Param( [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $VMPriority ); -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; -$projectDir = Split-Path (Split-Path $dir); +Write-Host "Starting execution of CreateSQLVM_azcli.ps1" +$__=$__ #quiesce warnings +$invocationDir = $PSScriptRoot +Push-Location -Path $invocationDir +$cfam = (Join-Path (Join-Path $invocationDir "../../Build/") "CommonFunctionsAndMethods.psm1" | Resolve-Path) +Write-Host "Attempting to load module from: $cfam" +Import-Module "$cfam" -Force -Verbose +Get-Module -Name CommonFunctionsAndMethods # Verify if module is loaded -.($projectDir+"\Build\CommonFunctionsAndMethods.ps1") Log-Output "<-><-><-><-><-><-><-><-><-><-><-><-><-><->"; -Log-Output "FileLocation: ", $dir; -Log-Output "Project Location: ", $projectDir; +Log-Output "FileLocation: ", $invocationDir; Log-Output "Parameters: ---------------------------"; Log-Output "Location:", $Location; Log-Output "Size:", $Size; @@ -64,20 +67,22 @@ $SQLVersionEditionHash = @{ "2008R2Std"=@{"sqlversion"="2008R2";"offer"="SQL2008R2SP3-WS2008R2SP1";"publisher"="microsoftsqlserver";"sku"="Standard";"osType"="Windows";"version"="latest";"bicep"="CreateSqlVirtualMachineTemplate-2008R2.bicep"}; #MicrosoftSQLServer:SQL2008R2SP3-WS2008R2SP1:Standard:latest "2012Ent"=@{"sqlversion"="2012";"offer"="SQL2012SP4-WS2012R2";"publisher"="microsoftsqlserver";"sku"="Enterprise";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"}; #MicrosoftSQLServer:SQL2012SP4-WS2012R2:Enterprise:latest "2014"=@{"sqlversion"="2014";"offer"="sql2014sp3-ws2012r2";"publisher"="microsoftsqlserver";"sku"="sqldev";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"}; #MicrosoftSQLServer:sql2014sp3-ws2012r2:sqldev:latest - "2016"=@{"sqlversion"="2016";"offer"="SQL2016SP2-WS2016";"publisher"="microsoftsqlserver";"sku"="sqldev";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"}; #MicrosoftSQLServer:sql2016sp2-ws2019:sqldev:latest + "2016"=@{"sqlversion"="2016";"offer"="sql2016sp3-ws2019";"publisher"="microsoftsqlserver";"sku"="sqldev";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"}; #MicrosoftSQLServer:sql2016sp2-ws2019:sqldev:latest "2017"=@{"sqlversion"="2017";"offer"="sql2017-ws2019";"publisher"="microsoftsqlserver";"sku"="sqldev";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"}; #MicrosoftSQLServer:sql2017-ws2019:sqldev:latest - "2019"=@{"sqlversion"="2019";"offer"="sql2019-ws2019";"publisher"="microsoftsqlserver";"sku"="sqldev";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"} #MicrosoftSQLServer:sql2019-ws2019:sqldev:latest + "2019"=@{"sqlversion"="2019";"offer"="sql2019-ws2022";"publisher"="microsoftsqlserver";"sku"="sqldev";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"} #MicrosoftSQLServer:sql2019-ws2019:sqldev:latest + "2022"=@{"sqlversion"="2022";"offer"="sql2022-ws2022";"publisher"="microsoftsqlserver";"sku"="sqldev-gen2";"osType"="Windows";"version"="latest";"bicep"="CreateSQLVirtualMachineTemplate.bicep"} #MicrosoftSQLServer:sql2022-ws2022:sqldev:latest }; $SQLVersionEditionInfo = $SQLVersionEditionHash.$SQLVersionEdition; $ImageUrn = $SQLVersionEditionInfo.publisher+":"+$SQLVersionEditionInfo.offer+":"+$SQLVersionEditionInfo.sku+":"+$SQLVersionEditionInfo.version; -$TemplateFile = $dir + "/" + $SQLVersionEditionInfo.bicep; +$TemplateFile = (Join-Path $invocationDir $SQLVersionEditionInfo.bicep | Resolve-Path); Log-Output "ImageUrn: ", $ImageUrn; Log-Output "SQLVersionEditionInfo: ", $SQLVersionEditionInfo; Log-Output "TemplateFile: ", $TemplateFile; Log-Output "START: Creating Resource Group $ResourceGroupName"; -$output = az group create --location "$Location" --name "$ResourceGroupName" | ConvertFrom-Json; + +$output = az group create --location "$Location" --name "$ResourceGroupName" --tags Department="tSQLtCI" Ephemeral="True" | ConvertFrom-Json; if (!$output) { Write-Error "Error creating Resource Group"; return @@ -177,7 +182,8 @@ $SQLVM|Out-String|Log-Output; Log-Output 'DONE: Applying SqlVM Config' Log-Output 'START: Prep SQL Server for tSQLt Build' -$DS = Invoke-Sqlcmd -InputFile "$dir/GetSQLServerVersion.sql" -ServerInstance "$FQDN,$SQLPort" -Username "$SQLUserName" -Password "$SQLPwd" -As DataSet -TrustServerCertificate +$GetSQLServerVersionPath = (Join-Path $invocationDir "GetSQLServerVersion.sql" | Resolve-Path) +$DS = Invoke-Sqlcmd -InputFile $GetSQLServerVersionPath -ServerInstance "$FQDN,$SQLPort" -Username "$SQLUserName" -Password "$SQLPwd" -As DataSet -TrustServerCertificate $DS.Tables[0].Rows | %{ Log-Output "{ $($_['LoginName']), $($_['TimeStamp']), $($_['VersionDetail']), $($_['ProductVersion']), $($_['ProductLevel']), $($_['SqlVersion']), $($_['ServerCollation']) }" } $ActualSQLVersion = $DS.Tables[0].Rows[0]['SqlVersion']; diff --git a/CI/Azure-DevOps/GetSQLServerVersion.sql b/CI/Azure-DevOps/GetSQLServerVersion.sql index f61061063..242b2135c 100644 --- a/CI/Azure-DevOps/GetSQLServerVersion.sql +++ b/CI/Azure-DevOps/GetSQLServerVersion.sql @@ -13,6 +13,7 @@ WHEN '13.0' THEN '2016' WHEN '14.0' THEN '2017' WHEN '15.0' THEN '2019' + WHEN '16.0' THEN '2022' ELSE 'Unknown' END SQLVersion, SERVERPROPERTY('Collation') AS ServerCollation \ No newline at end of file diff --git a/Examples/CreateDatabase.sql b/Examples/CreateDatabase.sql index a7a52c621..7184639fd 100644 --- a/Examples/CreateDatabase.sql +++ b/Examples/CreateDatabase.sql @@ -24,7 +24,7 @@ USE tempdb; DROP DATABASE tSQLt_Example; '); -CREATE DATABASE tSQLt_Example WITH TRUSTWORTHY ON; +CREATE DATABASE tSQLt_Example WITH TRUSTWORTHY OFF; GO USE tSQLt_Example; GO diff --git a/Examples/Examples.sqlproj b/Examples/Examples.sqlproj new file mode 100644 index 000000000..5a624ab4e --- /dev/null +++ b/Examples/Examples.sqlproj @@ -0,0 +1,13 @@ + + + + + Examples + {D2F3BB37-831A-4D07-89CC-4B9E1C9E9C07} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Experiments/CreateXEventSession_SSP&Batch.sql b/Experiments/CreateXEventSession_SSP&Batch.sql new file mode 100644 index 000000000..68b5145b8 --- /dev/null +++ b/Experiments/CreateXEventSession_SSP&Batch.sql @@ -0,0 +1,25 @@ +IF(EXISTS(SELECT * FROM sys.server_event_sessions WHERE name = 'MyXEventSession')) +BEGIN + DROP EVENT SESSION [MyXEventSession] ON SERVER; +END; +CREATE EVENT SESSION [MyXEventSession] ON SERVER +ADD EVENT sqlserver.rpc_completed ( + ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) + WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') +), +ADD EVENT sqlserver.rpc_starting ( + ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) + WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') +), +ADD EVENT sqlserver.sql_batch_completed ( + ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) + WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') +), +ADD EVENT sqlserver.sql_batch_starting ( + ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) + WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') +) +ADD TARGET package0.ring_buffer(SET max_memory=4096) -- Storing data in a ring buffer +WITH (MAX_MEMORY=4096 KB, EVENT_RETENTION_MODE=NO_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=ON, STARTUP_STATE=OFF) +GO +ALTER EVENT SESSION [MyXEventSession] ON SERVER STATE = START; \ No newline at end of file diff --git a/Experiments/Experiments.sqlproj b/Experiments/Experiments.sqlproj new file mode 100644 index 000000000..0a5c37cb6 --- /dev/null +++ b/Experiments/Experiments.sqlproj @@ -0,0 +1,13 @@ + + + + + Experiments + {67F0113D-7E17-41F4-961D-FA1E88969F9C} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Experiments/GenerateLargeXMLResult.sql b/Experiments/GenerateLargeXMLResult.sql new file mode 100644 index 000000000..09848a8df --- /dev/null +++ b/Experiments/GenerateLargeXMLResult.sql @@ -0,0 +1,3 @@ + +SELECT (SELECT * FROM sys.all_objects CROSS JOIN (SELECT TOP(1) ROW_NUMBER()OVER(ORDER BY (SELECT 1)) n FROM sys.all_objects) n FOR XML PATH(''),TYPE,ROOT('GH')) + diff --git a/Experiments/ReadXEventSession.sql b/Experiments/ReadXEventSession.sql new file mode 100644 index 000000000..3ebf609f0 --- /dev/null +++ b/Experiments/ReadXEventSession.sql @@ -0,0 +1,18 @@ +DECLARE @xml_output xml; + +-- Get the XML data from the ring buffer +SELECT @xml_output = CAST(xet.target_data AS xml) +FROM sys.dm_xe_session_targets AS xet +JOIN sys.dm_xe_sessions AS xe +ON (xe.address = xet.event_session_address) +WHERE xe.name = N'MyXEventSession' -- Replace with your session name +AND xet.target_name = N'ring_buffer'; +-- SELECT @xml_output +-- Parse and display the relevant information +SELECT + event_data.value('(@timestamp)[1]', 'datetime2') AS EventTime, + event_data.value('(data[@name="duration"]/value)[1]', 'int') AS Duration, + event_data.value('(action[@name="sql_text"]/value)[1]', 'nvarchar(max)') AS SqlText, + event_data.query('.') xx +FROM @xml_output.nodes('RingBufferTarget/event') AS XEventData(event_data) +ORDER BY EventTime; diff --git a/Facade/BuildOrder.txt b/Facade/BuildOrder.txt deleted file mode 100644 index 4b306bb54..000000000 --- a/Facade/BuildOrder.txt +++ /dev/null @@ -1,5 +0,0 @@ -../Build/temp/tSQLtBuild/Facade/CreateSourceDb.sql -../Build/temp/tSQLtBuild/Facade/CreateTargetDb.sql -../Build/temp/tSQLtBuild/Facade/SourceDbUseStatement.sql -../Build/temp/tSQLtBuild/tSQLt.class.sql -Facade.CreateAllObjects.ssp.sql diff --git a/Facade/Facade.CreateAllObjects.ssp.sql b/Facade/Facade.CreateAllObjects.ssp.sql deleted file mode 100644 index 955d4c3a7..000000000 --- a/Facade/Facade.CreateAllObjects.ssp.sql +++ /dev/null @@ -1,257 +0,0 @@ -EXEC tSQLt.DropClass 'Facade'; -GO -CREATE SCHEMA Facade; -GO -CREATE VIEW Facade.[sys.tables] AS SELECT * FROM sys.tables; -GO -CREATE VIEW Facade.[sys.views] AS SELECT * FROM sys.views; -GO -CREATE VIEW Facade.[sys.procedures] AS SELECT * FROM sys.procedures; -GO -CREATE VIEW Facade.[sys.objects] AS SELECT * FROM sys.objects; -GO -CREATE VIEW Facade.[sys.types] AS SELECT * FROM sys.types; -GO -CREATE PROCEDURE Facade.CreateSchemaIfNotExists - @FacadeDbName NVARCHAR(MAX), - @SchemaName NVARCHAR(MAX) -AS -BEGIN - DECLARE @ExecInRemoteDb NVARCHAR(MAX) = QUOTENAME(@FacadeDbName)+'.sys.sp_executesql'; - DECLARE @RemoteStatement NVARCHAR(MAX); - - DECLARE @RemoteSchemaId INT; - SET @RemoteStatement = N'SET @RemoteSchemaId = SCHEMA_ID(''' + REPLACE(PARSENAME(@SchemaName,1),'''','''''') +''');' - EXEC @ExecInRemoteDb @RemoteStatement, N'@RemoteSchemaId INT OUTPUT',@RemoteSchemaId OUT; - IF(@RemoteSchemaId IS NULL) - BEGIN - SET @RemoteStatement = 'EXEC(''CREATE SCHEMA ' + REPLACE(@SchemaName,'''','''''') +';'');'; - EXEC @ExecInRemoteDb @RemoteStatement,N''; - END; -END; -GO -CREATE PROCEDURE Facade.CreateSSPFacade - @FacadeDbName NVARCHAR(MAX), - @ProcedureObjectId INT -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = QUOTENAME(OBJECT_SCHEMA_NAME(@ProcedureObjectId)); - DECLARE @ProcedureName NVARCHAR(MAX) = @SchemaName+'.'+QUOTENAME(OBJECT_NAME(@ProcedureObjectId)); - DECLARE @CreateProcedureStatement NVARCHAR(MAX); - - EXEC tSQLt.Private_GenerateCreateProcedureSpyStatement - @ProcedureObjectId = @ProcedureObjectId, - @OriginalProcedureName = @ProcedureName, - @CreateProcedureStatement = @CreateProcedureStatement OUT, - @LogTableName = NULL, - @CommandToExecute = NULL, - @CallOriginal = 0, - @CreateLogTableStatement = NULL; - - EXEC Facade.CreateSchemaIfNotExists @FacadeDbName = @FacadeDbName, @SchemaName = @SchemaName; - - DECLARE @ExecInRemoteDb NVARCHAR(MAX) = QUOTENAME(@FacadeDbName)+'.sys.sp_executesql'; - DECLARE @RemoteStatement NVARCHAR(MAX); - - SET @RemoteStatement = 'EXEC(''' + REPLACE(@CreateProcedureStatement,'''','''''') + ''');'; - EXEC @ExecInRemoteDb @RemoteStatement,N''; -END; -GO -CREATE PROCEDURE Facade.CreateSSPFacades - @FacadeDbName NVARCHAR(MAX) -AS -BEGIN - DECLARE @cmd NVARCHAR(MAX) = - ( - SELECT 'EXEC Facade.CreateSSPFacade @FacadeDbName = @FacadeDbName, @ProcedureObjectId = '+CAST(object_id AS NVARCHAR(MAX))+';' - FROM Facade.[sys.procedures] - WHERE schema_id = SCHEMA_ID('tSQLt') - AND UPPER(name) NOT LIKE 'PRIVATE%' - FOR XML PATH(''),TYPE - ).value('.','NVARCHAR(MAX)'); - - EXEC sys.sp_executesql @cmd, N'@FacadeDbName NVARCHAR(MAX)', @FacadeDbName; -END; -GO -CREATE PROCEDURE Facade.CreateTableFacade - @FacadeDbName NVARCHAR(MAX), - @TableObjectId INT -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = QUOTENAME(OBJECT_SCHEMA_NAME(@TableObjectId)); - DECLARE @TableName NVARCHAR(MAX) = QUOTENAME(OBJECT_NAME(@TableObjectId)); - DECLARE @OrigTableFullName NVARCHAR(MAX) = @SchemaName+'.'+@TableName - DECLARE @CreateTableStatement NVARCHAR(MAX) = - (SELECT CreateTableStatement FROM tSQLt.Private_CreateFakeTableStatement(@TableObjectId,@OrigTableFullName,1,1,1,1)); - - EXEC Facade.CreateSchemaIfNotExists @FacadeDbName = @FacadeDbName, @SchemaName = @SchemaName; - - DECLARE @ExecInRemoteDb NVARCHAR(MAX) = QUOTENAME(@FacadeDbName)+'.sys.sp_executesql'; - DECLARE @RemoteStatement NVARCHAR(MAX); - - SET @RemoteStatement = 'EXEC(''' + REPLACE(@CreateTableStatement,'''','''''') + ''');'; - EXEC @ExecInRemoteDb @RemoteStatement,N''; -END; -GO -CREATE PROCEDURE Facade.CreateTableFacades - @FacadeDbName NVARCHAR(MAX) -AS -BEGIN - DECLARE @cmd NVARCHAR(MAX) = - ( - SELECT 'EXEC Facade.CreateTableFacade @FacadeDbName = @FacadeDbName, @TableObjectId = ' + CAST(object_id AS NVARCHAR(MAX)) + ';' - FROM Facade.[sys.tables] T - WHERE UPPER(T.name) NOT LIKE 'PRIVATE%' - AND T.schema_id = SCHEMA_ID('tSQLt') - FOR XML PATH (''),TYPE - ).value('.','NVARCHAR(MAX)'); - - EXEC sys.sp_executesql @cmd, N'@FacadeDbName NVARCHAR(MAX)', @FacadeDbName; - - RETURN; -END; -GO -CREATE PROCEDURE Facade.CreateViewFacade - @FacadeDbName NVARCHAR(MAX), - @ViewObjectId INT -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = QUOTENAME(OBJECT_SCHEMA_NAME(@ViewObjectId)); - DECLARE @ViewName NVARCHAR(MAX) = QUOTENAME(OBJECT_NAME(@ViewObjectId)); - DECLARE @OrigViewFullName NVARCHAR(MAX) = @SchemaName+'.'+@ViewName - DECLARE @CreateViewStatement NVARCHAR(MAX); - - SELECT @CreateViewStatement = - 'CREATE VIEW ' + @OrigViewFullName + - ' AS ' + - TypeOnlySelectStatement - FROM tSQLt.Private_CreateFakeFunctionStatement(@ViewObjectId, NULL); - - EXEC Facade.CreateSchemaIfNotExists @FacadeDbName = @FacadeDbName, @SchemaName = @SchemaName; - - DECLARE @ExecInRemoteDb NVARCHAR(MAX) = QUOTENAME(@FacadeDbName)+'.sys.sp_executesql'; - DECLARE @RemoteStatement NVARCHAR(MAX); - - SET @RemoteStatement = 'EXEC(''' + REPLACE(@CreateViewStatement,'''','''''') + ''');'; /* Wrapping this in an EXEC makes sure it is executed in its own "batch". */ - - EXEC @ExecInRemoteDb @RemoteStatement,N''; - RETURN; -END; -GO -CREATE PROCEDURE Facade.CreateViewFacades - @FacadeDbName NVARCHAR(MAX) -AS -BEGIN - DECLARE @cmd NVARCHAR(MAX) = - ( - SELECT 'EXEC Facade.CreateViewFacade @FacadeDbName = @FacadeDbName, @ViewObjectId = ' + CAST(object_id AS NVARCHAR(MAX)) + ';' - FROM Facade.[sys.views] V - WHERE UPPER(V.name) NOT LIKE 'PRIVATE%' - AND V.schema_id = SCHEMA_ID('tSQLt') - FOR XML PATH (''),TYPE - ).value('.','NVARCHAR(MAX)'); - - EXEC sys.sp_executesql @cmd, N'@FacadeDbName NVARCHAR(MAX)', @FacadeDbName; - RETURN; -END; -GO - -CREATE PROCEDURE Facade.CreateSFNFacade - @FacadeDbName NVARCHAR(MAX), - @FunctionObjectId INT -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = QUOTENAME(OBJECT_SCHEMA_NAME(@FunctionObjectId)); - - EXEC Facade.CreateSchemaIfNotExists @FacadeDbName = @FacadeDbName, @SchemaName = @SchemaName; - - DECLARE @ExecInRemoteDb NVARCHAR(MAX) = QUOTENAME(@FacadeDbName)+'.sys.sp_executesql'; - DECLARE @RemoteStatement NVARCHAR(MAX) = (SELECT CreateStatement FROM tSQLt.Private_CreateFakeFunctionStatement(@FunctionObjectId, NULL)); - - SET @RemoteStatement = 'EXEC('''+REPLACE(@RemoteStatement,'''','''''')+''');'; - - EXEC @ExecInRemoteDb @RemoteStatement,N''; -END; -GO -CREATE PROCEDURE Facade.CreateSFNFacades - @FacadeDbName NVARCHAR(MAX) -AS -BEGIN - DECLARE @cmd NVARCHAR(MAX) = - ( - SELECT 'EXEC Facade.CreateSFNFacade @FacadeDbName = @FacadeDbName, @FunctionObjectId = ' + CAST(object_id AS NVARCHAR(MAX)) + ';' - FROM Facade.[sys.objects] O - WHERE UPPER(O.name) NOT LIKE 'PRIVATE%' - AND O.schema_id = SCHEMA_ID('tSQLt') - AND O.type IN ('IF', 'TF', 'FS', 'FT', 'FN') - FOR XML PATH (''),TYPE - ).value('.','NVARCHAR(MAX)'); - - EXEC sys.sp_executesql @cmd, N'@FacadeDbName NVARCHAR(MAX)', @FacadeDbName; -END; -GO -CREATE PROCEDURE Facade.CreateTypeFacade - @FacadeDbName NVARCHAR(MAX), - @UserTypeId INT -AS -BEGIN - DECLARE @TypeTableObjectId INT; - DECLARE @TypeSchemaId INT; - SELECT @TypeTableObjectId = tt.type_table_object_id, @TypeSchemaId = tt.schema_id FROM sys.table_types tt WHERE tt.user_type_id = @UserTypeId; - - IF (@TypeTableObjectId IS NULL) - BEGIN - RAISERROR ('CreateTypeFacade currently handles only TABLE_TYPEs', 16, 10); - RETURN; - END - - DECLARE @SchemaName NVARCHAR(MAX) = QUOTENAME(SCHEMA_NAME(@TypeSchemaId)); - DECLARE @TypeName NVARCHAR(MAX) = QUOTENAME(TYPE_NAME(@UserTypeId)); - - DECLARE @FullTypeName NVARCHAR(MAX) = @SchemaName+'.'+@TypeName; - DECLARE @CreateTableStatement NVARCHAR(MAX) = - (SELECT CreateTableTypeStatement FROM tSQLt.Private_CreateFakeTableStatement(@TypeTableObjectId,@FullTypeName,1,1,1,1)); - - EXEC Facade.CreateSchemaIfNotExists @FacadeDbName = @FacadeDbName, @SchemaName = @SchemaName; - - DECLARE @ExecInRemoteDb NVARCHAR(MAX) = QUOTENAME(@FacadeDbName)+'.sys.sp_executesql'; - DECLARE @RemoteStatement NVARCHAR(MAX); - - SET @RemoteStatement = 'EXEC(''' + REPLACE(@CreateTableStatement,'''','''''') + ''');'; - EXEC @ExecInRemoteDb @RemoteStatement,N''; - -END; -GO -CREATE PROCEDURE Facade.CreateTypeFacades - @FacadeDbName NVARCHAR(MAX) -AS -BEGIN - DECLARE @cmd NVARCHAR(MAX) = - ( - SELECT 'EXEC Facade.CreateTypeFacade @FacadeDbName = @FacadeDbName, @UserTypeId = ' + CAST(t.user_type_id AS NVARCHAR(MAX)) + ';' - FROM Facade.[sys.types] t - WHERE t.schema_id = SCHEMA_ID('tSQLt') - AND UPPER(t.name) NOT LIKE ('PRIVATE%') - FOR XML PATH (''),TYPE - ).value('.','NVARCHAR(MAX)'); - - EXEC sys.sp_executesql @cmd, N'@FacadeDbName NVARCHAR(MAX)', @FacadeDbName; -END; -GO -CREATE PROCEDURE Facade.CreateAllFacadeObjects - @FacadeDbName NVARCHAR(MAX) -AS -BEGIN - - EXEC Facade.CreateTypeFacades @FacadeDbName = @FacadeDbName; - EXEC Facade.CreateTableFacades @FacadeDbName = @FacadeDbName; - EXEC Facade.CreateViewFacades @FacadeDbName = @FacadeDbName; - EXEC Facade.CreateSSPFacades @FacadeDbName = @FacadeDbName; - EXEC Facade.CreateSFNFacades @FacadeDbName = @FacadeDbName; - - DECLARE @ExecuteInFacadeDb NVARCHAR(MAX) = @FacadeDbName + '.sys.sp_executesql'; - EXEC @ExecuteInFacadeDb N'CREATE USER [tSQLt.TestClass] WITHOUT LOGIN;', N''; - -END; -GO - diff --git a/Facade/Facade.ssmssqlproj b/Facade/Facade.ssmssqlproj deleted file mode 100644 index b5a77254c..000000000 --- a/Facade/Facade.ssmssqlproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - Facade.CreateAllObjects.ssp.sql - - - - - - - - - - buildFacadeScripts.ps1 - - - - - - BuildOrder.txt - - - - - \ No newline at end of file diff --git a/Facade/buildFacadeScripts.ps1 b/Facade/buildFacadeScripts.ps1 deleted file mode 100644 index 001f0e526..000000000 --- a/Facade/buildFacadeScripts.ps1 +++ /dev/null @@ -1,28 +0,0 @@ - -Push-Location; - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; -#Log-Output "FileLocation: $dir"; -Set-Location $dir; - -$createBuildDb = Get-Content "../Build/CreateBuildDb.sql"; - -Set-Content "../Build/temp/tSQLtBuild/Facade/CreateSourceDb.sql" $createBuildDb.Replace('$(NewDbName)', '$(FacadeSourceDb)'); -Set-Content "../Build/temp/tSQLtBuild/Facade/CreateTargetDb.sql" $createBuildDb.Replace('$(NewDbName)', '$(FacadeTargetDb)'); - -$sourceDbUseStatement = 'USE $(FacadeSourceDb);' -Set-Content "../Build/temp/tSQLtBuild/Facade/SourceDbUseStatement.sql" $sourceDbUseStatement; - -../Build/BuildHelper.exe "BuildOrder.txt" "../Build/temp/tSQLtBuild/Facade/FacadeScript.sql" - -$executeFacadeScript = @' - :r FacadeScript.sql - GO - EXEC Facade.CreateAllFacadeObjects @FacadeDbName='$(FacadeTargetDb)'; - GO -'@; - -Set-Content "../Build/temp/tSQLtBuild/Facade/ExecuteFacadeScript.sql" $executeFacadeScript; - -Pop-Location; \ No newline at end of file diff --git a/FacadeTests/FacadeTests.ssmssqlproj b/FacadeTests/FacadeTests.ssmssqlproj deleted file mode 100644 index 11a10a819..000000000 --- a/FacadeTests/FacadeTests.ssmssqlproj +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - Facade_CreateFacadeDb_Tests.class.sql - - - - - - Facade_CreateTableFacades_Tests.class.sql - - - - - - Facade_CreateViewFacades_Tests.class.sql - - - - - - Facade_Dacpac_Tests.class.sql - - - - - - - - - - buildFacadeTests.ps1 - - - - - \ No newline at end of file diff --git a/FacadeTests/Facade_CreateFacadeDb_Tests.class.sql b/FacadeTests/Facade_CreateFacadeDb_Tests.class.sql deleted file mode 100644 index f1925da9e..000000000 --- a/FacadeTests/Facade_CreateFacadeDb_Tests.class.sql +++ /dev/null @@ -1,708 +0,0 @@ -:SETVAR FacadeTargetDb tSQLtFacade ----Build+ -GO -EXEC tSQLt.NewTestClass 'Facade_CreateFacadeDb_Tests'; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade calls Private_GenerateCreateProcedureSpyStatement] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_GenerateCreateProcedureSpyStatement'; - - EXEC('CREATE PROC dbo.AProc AS RETURN;'); - DECLARE @ProcedureObjectId INT = OBJECT_ID('dbo.AProc'); - - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = @ProcedureObjectId; - - SELECT - ProcedureObjectId, - OriginalProcedureName - INTO #Actual FROM tSQLt.Private_GenerateCreateProcedureSpyStatement_SpyProcedureLog; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - - INSERT INTO #Expected - VALUES(@ProcedureObjectId,'[dbo].[AProc]'); - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade passes NULL in @LogTableName & @CommandToExecute for Private_GenerateCreateProcedureSpyStatement] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_GenerateCreateProcedureSpyStatement'; - - EXEC('CREATE PROC dbo.AProc AS RETURN;'); - DECLARE @ProcedureObjectId INT = OBJECT_ID('dbo.AProc'); - - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = @ProcedureObjectId; - - SELECT - LogTableName, - CommandToExecute - INTO #Actual FROM tSQLt.Private_GenerateCreateProcedureSpyStatement_SpyProcedureLog; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - - INSERT INTO #Expected - VALUES(NULL,NULL); - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade executes @CreateProcedureStatement from Private_GenerateCreateProcedureSpyStatement in facade db] -AS -BEGIN - EXEC tSQLt.SpyProcedure - @ProcedureName = 'tSQLt.Private_GenerateCreateProcedureSpyStatement', - @CommandToExecute='SET @CreateProcedureStatement = ''CREATE PROCEDURE dbo.AProc AS RETURN;'';'; - - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = NULL; - - DECLARE @Actual NVARCHAR(MAX); - SELECT @Actual = definition FROM $(FacadeTargetDb).sys.sql_modules WHERE object_id = OBJECT_ID('$(FacadeTargetDb).dbo.AProc'); - - EXEC tSQLt.AssertEqualsString @Expected = 'CREATE PROCEDURE dbo.AProc AS RETURN;', @Actual = @Actual; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade works for other schema that does exist in the facade db] -AS -BEGIN - EXEC('CREATE SCHEMA SomeOtherSchemaForFacadeTests;'); - EXEC $(FacadeTargetDb).sys.sp_executesql N'EXEC(''CREATE SCHEMA SomeOtherSchemaForFacadeTests;'');',N''; - - EXEC('CREATE PROC SomeOtherSchemaForFacadeTests.AnotherProc AS RETURN 42;'); - DECLARE @ProcedureObjectId INT = OBJECT_ID('SomeOtherSchemaForFacadeTests.AnotherProc'); - - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = @ProcedureObjectId; - - EXEC tSQLt.AssertObjectExists @ObjectName = '$(FacadeTargetDb).SomeOtherSchemaForFacadeTests.AnotherProc'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade works for other schema that does NOT exist in the facade db] -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = 'SomeRandomSchema'+CONVERT(NVARCHAR(MAX),CAST(NEWID() AS VARBINARY(MAX)),2); - DECLARE @cmd NVARCHAR(MAX); - - SET @cmd = 'CREATE SCHEMA '+@SchemaName+';'; - EXEC(@cmd); - - SET @cmd = 'CREATE PROC '+@SchemaName+'.AnotherProc AS RETURN 42;'; - EXEC(@cmd); - - - DECLARE @ProcedureObjectId INT = OBJECT_ID(@SchemaName+'.AnotherProc'); - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = @ProcedureObjectId; - - - DECLARE @RemoteProcedureName NVARCHAR(MAX) = '$(FacadeTargetDb).'+@SchemaName+'.AnotherProc'; - EXEC tSQLt.AssertObjectExists @ObjectName = @RemoteProcedureName; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test Facade.sys.procedures exists] -AS -BEGIN - SELECT * INTO #Actual FROM Facade.[sys.procedures]; - SELECT * INTO #Expected FROM sys.procedures; - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacades doesn't call CreateSSPFacade if there's no SSP] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.procedures]'; - - EXEC Facade.CreateSSPFacades @FacadeDbName = '$(FacadeTargetDb)'; - - EXEC tSQLt.AssertEmptyTable @TableName = 'Facade.[CreateSSPFacade_SpyProcedureLog]'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacades calls CreateSSPFacade for single SSP] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.procedures]'; - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''AProc'');'); - - EXEC Facade.CreateSSPFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT ProcedureObjectId INTO #Actual FROM Facade.[CreateSSPFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacades calls CreateSSPFacade for multiple SSPs] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.procedures]'; - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''AProc1'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1002,SCHEMA_ID(''tSQLt''),''AProc2'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1003,SCHEMA_ID(''tSQLt''),''AProc3'');'); - - EXEC Facade.CreateSSPFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT ProcedureObjectId INTO #Actual FROM Facade.[CreateSSPFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1002),(1003); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacades calls CreateSSPFacade for schema tSQLt only] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.procedures]'; - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''AProc1'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1002,SCHEMA_ID(''dbo''),''AProc2'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1003,SCHEMA_ID(''tSQLt''),''AProc3'');'); - - EXEC Facade.CreateSSPFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT ProcedureObjectId INTO #Actual FROM Facade.[CreateSSPFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1003); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacades ignores Private SSPs] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.procedures]'; - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''AProc1'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1002,SCHEMA_ID(''tSQLt''),''Private_AProc2'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1003,SCHEMA_ID(''tSQLt''),''PrivateProc3'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1004,SCHEMA_ID(''tSQLt''),''PrIVateProc3'');'); - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1005,SCHEMA_ID(''tSQLt''),''PRIVATEProc3'');'); - - EXEC Facade.CreateSSPFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT ProcedureObjectId INTO #Actual FROM Facade.[CreateSSPFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - - -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacade executes the statement returned from tSQLt.Private_CreateFakeFunctionStatement in the facade db] -AS -BEGIN - EXEC tSQLt.FakeFunction @FunctionName = N'tSQLt.Private_CreateFakeFunctionStatement', - @FakeDataSource = N'SELECT ''CREATE FUNCTION dbo.aRandomFunction () RETURNS INT AS BEGIN RETURN 1; END;'' CreateStatement'; - - EXEC Facade.CreateSFNFacade @FacadeDbName = '$(FacadeTargetDb)', @FunctionObjectId = NULL; - - SELECT 'Is a function.' AS resultColumn INTO #Actual - FROM $(FacadeTargetDb).sys.objects O - JOIN $(FacadeTargetDb).sys.schemas S ON (O.schema_id = S.schema_id) - WHERE O.name = 'aRandomFunction' - AND S.name = 'dbo' - AND O.type = 'FN'; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - - INSERT INTO #Expected VALUES ('Is a function.'); - - EXEC tSQLt.AssertEqualsTable @Expected = N'#Expected', @Actual = N'#Actual'; -END; -GO -CREATE FUNCTION Facade_CreateFacadeDb_Tests.[THROW @FunctionObjectId] -( - @FunctionObjectId INT, - @ReturnValue NVARCHAR(MAX) -) -RETURNS TABLE -AS -RETURN SELECT 'RAISERROR (''@FunctionObjectId=%i'',16,1,' + CAST(@FunctionObjectId AS NVARCHAR(MAX)) + ');' CreateStatement; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacade passes the correct object id to tSQLt.Private_CreateFakeFunctionStatement] -AS -BEGIN - EXEC tSQLt.FakeFunction @FunctionName = N'tSQLt.Private_CreateFakeFunctionStatement', - @FakeFunctionName = 'Facade_CreateFacadeDb_Tests.[THROW @FunctionObjectId]'; - - EXEC tSQLt.ExpectException @ExpectedMessage = N'@FunctionObjectId=4217'; - - EXEC Facade.CreateSFNFacade @FacadeDbName = '$(FacadeTargetDb)', @FunctionObjectId = 4217; - -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacade creates schema if it doesn't already exist] -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = 'SomeRandomSchema'+CONVERT(NVARCHAR(MAX),CAST(NEWID() AS VARBINARY(MAX)),2); - DECLARE @FakeDataSourceStatement NVARCHAR(MAX) = N'SELECT ''CREATE FUNCTION ' + @SchemaName + '.aRandomFunction () RETURNS INT AS BEGIN RETURN 1; END;'' CreateStatement'; - DECLARE @cmd NVARCHAR(MAX) = 'CREATE SCHEMA ' + @SchemaName; - DECLARE @FunctionObjectId INT; - - EXEC (@cmd); - EXEC ('CREATE FUNCTION ' + @SchemaName + '.aRandomFunction () RETURNS INT AS BEGIN RETURN 1; END;'); - SET @FunctionObjectId = OBJECT_ID(@SchemaName + '.aRandomFunction'); - - EXEC tSQLt.FakeFunction @FunctionName = N'tSQLt.Private_CreateFakeFunctionStatement', - @FakeDataSource = @FakeDataSourceStatement; - - EXEC Facade.CreateSFNFacade @FacadeDbName = '$(FacadeTargetDb)', @FunctionObjectId = @FunctionObjectId; - - SELECT 'Is a function.' AS resultColumn INTO #Actual - FROM $(FacadeTargetDb).sys.objects O - JOIN $(FacadeTargetDb).sys.schemas S ON (O.schema_id = S.schema_id) - WHERE O.name = 'aRandomFunction' - AND S.name = @SchemaName - AND O.type = 'FN'; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - - INSERT INTO #Expected VALUES ('Is a function.'); - - EXEC tSQLt.AssertEqualsTable @Expected = N'#Expected', @Actual = N'#Actual'; END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade works for schema with single quote] -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = QUOTENAME('SomeRandomSchema'''+CONVERT(NVARCHAR(MAX),CAST(NEWID() AS VARBINARY(MAX)),2)); - DECLARE @cmd NVARCHAR(MAX); - - SET @cmd = 'CREATE SCHEMA ' + @SchemaName + ';'; - EXEC(@cmd); - - SET @cmd = 'CREATE PROC ' + @SchemaName + '.AnotherProc AS RETURN 42;'; - EXEC(@cmd); - - DECLARE @ProcedureObjectId INT = OBJECT_ID(@SchemaName+'.AnotherProc'); - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = @ProcedureObjectId; - - DECLARE @RemoteProcedureName NVARCHAR(MAX) = '$(FacadeTargetDb).'+@SchemaName+'.AnotherProc'; - EXEC tSQLt.AssertObjectExists @ObjectName = @RemoteProcedureName; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacade works for procedure names with single quote] -AS -BEGIN - DECLARE @cmd NVARCHAR(MAX); - - SET @cmd = 'CREATE PROC dbo.[Anothe''rProc] AS RETURN 42;'; - EXEC(@cmd); - - DECLARE @ProcedureObjectId INT = OBJECT_ID('dbo.[Anothe''rProc]'); - EXEC Facade.CreateSSPFacade @FacadeDbName = '$(FacadeTargetDb)', @ProcedureObjectId = @ProcedureObjectId; - - DECLARE @RemoteProcedureName NVARCHAR(MAX) = '$(FacadeTargetDb).dbo.[Anothe''rProc]'; - EXEC tSQLt.AssertObjectExists @ObjectName = @RemoteProcedureName; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacade works for function names with single quote] -AS -BEGIN - DECLARE @FakeDataSourceStatement NVARCHAR(MAX) = N'SELECT ''CREATE FUNCTION dbo.[aRando''''mFunction] () RETURNS INT AS BEGIN RETURN 1; END;'' CreateStatement'; - DECLARE @FunctionObjectId INT; - - EXEC ('CREATE FUNCTION dbo.[aRando''mFunction] () RETURNS INT AS BEGIN RETURN 1; END;'); - SET @FunctionObjectId = OBJECT_ID('dbo.[aRando''mFunction]'); - - EXEC tSQLt.FakeFunction @FunctionName = N'tSQLt.Private_CreateFakeFunctionStatement', - @FakeDataSource = @FakeDataSourceStatement; - - EXEC Facade.CreateSFNFacade @FacadeDbName = '$(FacadeTargetDb)', @FunctionObjectId = @FunctionObjectId; - - SELECT 'Is a function.' AS resultColumn INTO #Actual - FROM $(FacadeTargetDb).sys.objects O - JOIN $(FacadeTargetDb).sys.schemas S ON (O.schema_id = S.schema_id) - WHERE O.name = 'aRando''mFunction' - AND S.name = 'dbo' - AND O.type = 'FN'; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - - INSERT INTO #Expected VALUES ('Is a function.'); - - EXEC tSQLt.AssertEqualsTable @Expected = N'#Expected', @Actual = N'#Actual'; - -END; -GO - -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSSPFacades passes @FacadeDbName to CreateSSPFacade] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.procedures]'; - EXEC('INSERT INTO Facade.[sys.procedures](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''AProc'');'); - - EXEC Facade.CreateSSPFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName INTO #Actual FROM Facade.[CreateSSPFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)'); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacades doesn't call CreateSFNFacade if there are no functions] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.objects]'; - - EXEC Facade.CreateSFNFacades @FacadeDbName = '$(FacadeTargetDb)'; - - EXEC tSQLt.AssertEmptyTable @TableName = 'Facade.[CreateSFNFacade_SpyProcedureLog]'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacades calls CreateSFNFacade if there is one function] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.objects]'; - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomFunction'',''FN'');'); - - EXEC Facade.CreateSFNFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName, FunctionObjectId INTO #Actual FROM Facade.[CreateSFNFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 1001); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; - -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacades calls CreateSFNFacade if there are multiple functions] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.objects]'; - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1003,SCHEMA_ID(''tSQLt''),''cRandomFunction'',''FN'');'); - - EXEC Facade.CreateSFNFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName, FunctionObjectId INTO #Actual FROM Facade.[CreateSFNFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 1001), ('$(FacadeTargetDb)', 1002), ('$(FacadeTargetDb)', 1003); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; - -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacades calls CreateSFNFacade only for functions which are not Private] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.objects]'; - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1002,SCHEMA_ID(''tSQLt''),''PrivateRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1003,SCHEMA_ID(''tSQLt''),''PrIVateRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1004,SCHEMA_ID(''tSQLt''),''PRIVATERandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1005,SCHEMA_ID(''tSQLt''),''cRandomFunction'',''FN'');'); - - EXEC Facade.CreateSFNFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FunctionObjectId INTO #Actual FROM Facade.[CreateSFNFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001), (1005); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; - -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacades calls CreateSFNFacade only for functions which are in the tSQLt schema] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.objects]'; - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomFunction'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1003,SCHEMA_ID(''dbo''),''cRandomFunction'',''FN'');'); - - EXEC Facade.CreateSFNFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FunctionObjectId INTO #Actual FROM Facade.[CreateSFNFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001), (1002); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; - -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateSFNFacades calls CreateSFNFacade only for functions] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.objects]'; - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomObject'',''IF'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1003,SCHEMA_ID(''tSQLt''),''cRandomObject'',''TF'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1004,SCHEMA_ID(''tSQLt''),''dRandomObject'',''FS'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1005,SCHEMA_ID(''tSQLt''),''eRandomObject'',''FT'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomObject'',''FN'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1006,SCHEMA_ID(''tSQLt''),''fRandomObject'',''P'');'); - EXEC('INSERT INTO Facade.[sys.objects](object_id,schema_id,name,type)VALUES (1007,SCHEMA_ID(''tSQLt''),''gRandomObject'',''SN'');'); - - EXEC Facade.CreateSFNFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FunctionObjectId INTO #Actual FROM Facade.[CreateSFNFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001), (1002), (1003), (1004), (1005); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; - -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacade copies a simple table type to the facade db] -AS -BEGIN - CREATE TYPE dbo.SomeRandomType AS TABLE (a INT); - - DECLARE @UserTypeId INT = TYPE_ID('dbo.SomeRandomType'); - - EXEC Facade.CreateTypeFacade @FacadeDbName = '$(FacadeTargetDb)', @UserTypeId = @UserTypeId; - - DECLARE @RemoteTypeId INT; - EXEC $(FacadeTargetDb).sys.sp_executesql N'SET @TypeId = (SELECT TYPE_ID(''dbo.SomeRandomType''));',N'@TypeId INT OUTPUT', @RemoteTypeId OUT; - - EXEC tSQLt.AssertNotEquals @Expected=NULL, @Actual = @RemoteTypeId, @Message = N'Remote Type not found. '; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacade errors with appropriate message if type is not a table_type] -AS -BEGIN - CREATE TYPE dbo.SomeRandomType FROM INT; - DECLARE @UserTypeId INT = TYPE_ID('dbo.SomeRandomType'); - - EXEC tSQLt.ExpectException @ExpectedMessagePattern = '%CreateTypeFacade currently handles only TABLE_TYPEs%', @ExpectedSeverity = 16, @ExpectedState = 10; - - EXEC Facade.CreateTypeFacade @FacadeDbName = '$(FacadeTargetDb)', @UserTypeId = @UserTypeId; -END; -GO - -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacade works for other schema that does exist in the facade db] -AS -BEGIN - EXEC('CREATE SCHEMA SomeOtherSchemaForFacadeTests;'); - EXEC $(FacadeTargetDb).sys.sp_executesql N'EXEC(''CREATE SCHEMA SomeOtherSchemaForFacadeTests;'');',N''; - - CREATE TYPE SomeOtherSchemaForFacadeTests.SomeRandomType AS TABLE (a INT); - - DECLARE @UserTypeId INT = TYPE_ID('SomeOtherSchemaForFacadeTests.SomeRandomType'); - - EXEC Facade.CreateTypeFacade @FacadeDbName = '$(FacadeTargetDb)', @UserTypeId = @UserTypeId; - - DECLARE @RemoteTypeId INT; - EXEC $(FacadeTargetDb).sys.sp_executesql N'SET @TypeId = (SELECT TYPE_ID(''SomeOtherSchemaForFacadeTests.SomeRandomType''));',N'@TypeId INT OUTPUT', @RemoteTypeId OUT; - - EXEC tSQLt.AssertNotEquals @Expected=NULL, @Actual = @RemoteTypeId, @Message = N'Remote Type not found. '; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacade copies table type into a schema that does not exist in the facade db] -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = 'SomeRandomSchema'+CONVERT(NVARCHAR(MAX),CAST(NEWID() AS VARBINARY(MAX)),2); - DECLARE @cmd NVARCHAR(MAX); - - SET @cmd = 'CREATE SCHEMA '+@SchemaName+';'; - EXEC(@cmd); - - SET @cmd = 'CREATE TYPE ' + @SchemaName + '.SomeRandomType AS TABLE (a INT);'; - EXEC(@cmd); - - DECLARE @UserTypeId INT = TYPE_ID(@SchemaName + '.SomeRandomType'); - EXEC Facade.CreateTypeFacade @FacadeDbName = '$(FacadeTargetDb)', @UserTypeId = @UserTypeId; - - DECLARE @RemoteTypeId INT; - SET @cmd = 'SET @TypeId = (SELECT TYPE_ID(''' + @SchemaName + '.SomeRandomType''));'; - EXEC $(FacadeTargetDb).sys.sp_executesql @cmd,N'@TypeId INT OUTPUT', @RemoteTypeId OUT; - - EXEC tSQLt.AssertNotEquals @Expected=NULL, @Actual = @RemoteTypeId, @Message = N'Remote Type not found. '; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacade copies table type with multiple columns to the facade db] -AS -BEGIN - CREATE TYPE dbo.SomeRandomType AS TABLE (a INT, bb NVARCHAR(MAX), ccc DATETIME2); - - DECLARE @UserTypeId INT = TYPE_ID('dbo.SomeRandomType'); - - EXEC Facade.CreateTypeFacade @FacadeDbName = '$(FacadeTargetDb)', @UserTypeId = @UserTypeId; - - DECLARE @LocalTypeTableObjectId INT = (SELECT t.type_table_object_id FROM sys.table_types t WHERE t.user_type_id = @UserTypeId); - - DECLARE @RemoteTypeTableObjectId INT; - EXEC $(FacadeTargetDb).sys.sp_executesql N'SET @RemoteTypeTableObjectId = (SELECT t.type_table_object_id FROM sys.table_types t WHERE t.user_type_id = TYPE_ID(''dbo.SomeRandomType''));',N'@RemoteTypeTableObjectId INT OUTPUT', @RemoteTypeTableObjectId OUT; - - SELECT - C.name, - C.column_id, - C.system_type_id, - C.user_type_id, - C.max_length, - C.precision, - C.scale, - C.is_nullable, - C.is_identity - INTO #Actual FROM $(FacadeTargetDb).sys.columns AS C WHERE C.object_id = @RemoteTypeTableObjectId; - - SELECT - C.name, - C.column_id, - C.system_type_id, - C.user_type_id, - C.max_length, - C.precision, - C.scale, - C.is_nullable, - C.is_identity - INTO #Expected FROM sys.columns AS C WHERE C.object_id = @LocalTypeTableObjectId; - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacades doesn't call CreateTypeFacade if there are no types] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.types]'; - - EXEC Facade.CreateTypeFacades @FacadeDbName = '$(FacadeTargetDb)'; - - EXEC tSQLt.AssertEmptyTable @TableName = 'Facade.[CreateTypeFacade_SpyProcedureLog]'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacades calls CreateTypeFacade once if there is one type] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.types]'; - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (101, SCHEMA_ID(''tSQLt''),''aType'');'); - - EXEC Facade.CreateTypeFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName, UserTypeId INTO #Actual FROM Facade.[CreateTypeFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 101); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacades calls CreateTypeFacade once each for multiple types] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.types]'; - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (101, SCHEMA_ID(''tSQLt''),''aType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (102, SCHEMA_ID(''tSQLt''),''bType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (103, SCHEMA_ID(''tSQLt''),''cType'');'); - - EXEC Facade.CreateTypeFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName, UserTypeId INTO #Actual FROM Facade.[CreateTypeFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 101),('$(FacadeTargetDb)', 102),('$(FacadeTargetDb)', 103); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacades calls CreateTypeFacade only for types which are in the tSQLt schema] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.types]'; - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (101, SCHEMA_ID(''tSQLt''),''aType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (102, SCHEMA_ID(''dbo''),''bType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (103, SCHEMA_ID(''tSQLt''),''cType'');'); - - EXEC Facade.CreateTypeFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName, UserTypeId INTO #Actual FROM Facade.[CreateTypeFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 101),('$(FacadeTargetDb)', 103); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateTypeFacades calls CreateTypeFacade only for types which are not Private] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.types]'; - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (101, SCHEMA_ID(''tSQLt''),''aType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (102, SCHEMA_ID(''tSQLt''),''bType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (103, SCHEMA_ID(''tSQLt''),''PrivateType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (104, SCHEMA_ID(''tSQLt''),''PRIVATEType'');'); - EXEC ('INSERT INTO Facade.[sys.types] (user_type_id, schema_id, name) VALUES (105, SCHEMA_ID(''tSQLt''),''PrIVateType'');'); - - EXEC Facade.CreateTypeFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName, UserTypeId INTO #Actual FROM Facade.[CreateTypeFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 101),('$(FacadeTargetDb)', 102); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateAllFacadeObjects calls all Facades procedures] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacades'; - - EXEC Facade.CreateAllFacadeObjects @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT * INTO #Actual FROM - ( - SELECT FacadeDbName, 'UDT' AS [Procedure] FROM Facade.[CreateTypeFacades_SpyProcedureLog] - UNION ALL - SELECT FacadeDbName, 'SFN' AS [Procedure] FROM Facade.[CreateSFNFacades_SpyProcedureLog] - UNION ALL - SELECT FacadeDbName, 'SSP' AS [Procedure] FROM Facade.[CreateSSPFacades_SpyProcedureLog] - UNION ALL - SELECT FacadeDbName, 'TBL' AS [Procedure] FROM Facade.[CreateTableFacades_SpyProcedureLog] - UNION ALL - SELECT FacadeDbName, 'VW' AS [Procedure] FROM Facade.[CreateViewFacades_SpyProcedureLog] - ) SPL; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)','UDT'),('$(FacadeTargetDb)','SFN'), ('$(FacadeTargetDb)','SSP'), ('$(FacadeTargetDb)','TBL'), ('$(FacadeTargetDb)','VW'); - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateAllFacadeObjects doesn't error] -AS -BEGIN - EXEC tSQLt.ExpectNoException; - - EXEC Facade.CreateAllFacadeObjects @FacadeDbName = '$(FacadeTargetDb)'; -END; -GO -CREATE PROCEDURE Facade_CreateFacadeDb_Tests.[test CreateAllFacadeObjects creates the tSQLt.TestClass user] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSFNFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateSSPFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacades'; - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTypeFacades'; - - EXEC Facade.CreateAllFacadeObjects @FacadeDbName = '$(FacadeTargetDb)'; - - DECLARE @RemoteDatabasePrincipalId INT; - EXEC $(FacadeTargetDb).sys.sp_executesql N'SET @RemoteDatabasePrincipalId = USER_ID(''tSQLt.TestClass'');',N'@RemoteDatabasePrincipalId INT OUTPUT', @RemoteDatabasePrincipalId OUT; - - EXEC tSQLt.AssertNotEquals @Expected=NULL, @Actual = @RemoteDatabasePrincipalId, @Message = N'Remote Database Principal Id not found. '; -END; -GO diff --git a/FacadeTests/Facade_CreateTableFacades_Tests.class.sql b/FacadeTests/Facade_CreateTableFacades_Tests.class.sql deleted file mode 100644 index 12a543c5a..000000000 --- a/FacadeTests/Facade_CreateTableFacades_Tests.class.sql +++ /dev/null @@ -1,231 +0,0 @@ -:SETVAR FacadeTargetDb tSQLtFacade ----Build+ -GO -EXEC tSQLt.NewTestClass 'Facade_CreateTableFacades_Tests'; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacade copies a simple table to the facade db] -AS -BEGIN - CREATE TABLE dbo.SomeRandomTable(a INT); - - DECLARE @TableObjectId INT = OBJECT_ID('dbo.SomeRandomTable'); - - EXEC Facade.CreateTableFacade @FacadeDbName = '$(FacadeTargetDb)', @TableObjectId = @TableObjectId; - - EXEC tSQLt.AssertObjectExists @ObjectName = '$(FacadeTargetDb).dbo.SomeRandomTable'; -END; -GO - -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacade copies another table to the facade db] -AS -BEGIN - CREATE TABLE dbo.SomeOtherTable(a INT); - - DECLARE @TableObjectId INT = OBJECT_ID('dbo.SomeOtherTable'); - - EXEC Facade.CreateTableFacade @FacadeDbName = '$(FacadeTargetDb)', @TableObjectId = @TableObjectId; - - EXEC tSQLt.AssertObjectExists @ObjectName = '$(FacadeTargetDb).dbo.SomeOtherTable'; -END; -GO - -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacade copies table into a schema that does not exist in the facade db] -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = 'SomeRandomSchema'+CONVERT(NVARCHAR(MAX),CAST(NEWID() AS VARBINARY(MAX)),2); - DECLARE @cmd NVARCHAR(MAX); - - SET @cmd = 'CREATE SCHEMA '+@SchemaName+';'; - EXEC(@cmd); - - SET @cmd = 'CREATE TABLE '+@SchemaName+'.SomeTable(a INT);'; - EXEC(@cmd); - - DECLARE @TableObjectId INT = OBJECT_ID(@SchemaName+'.SomeTable'); - - EXEC Facade.CreateTableFacade @FacadeDbName = '$(FacadeTargetDb)', @TableObjectId = @TableObjectId; - - DECLARE @RemoteObjectName NVARCHAR(MAX) = '$(FacadeTargetDb).'+@SchemaName+'.SomeTable'; - EXEC tSQLt.AssertObjectExists @ObjectName = @RemoteObjectName; -END; -GO - - -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacade copies all columns with their data types] -AS -BEGIN - CREATE TABLE dbo.SomeOtherTable(a INT IDENTITY(1,1), bb CHAR(1) NULL, ccc DATETIME NOT NULL, dddd NVARCHAR(MAX)); - - DECLARE @TableObjectId INT = OBJECT_ID('dbo.SomeOtherTable'); - - EXEC Facade.CreateTableFacade @FacadeDbName = '$(FacadeTargetDb)', @TableObjectId = @TableObjectId; - - SELECT - C.name, - C.column_id, - C.system_type_id, - C.user_type_id, - C.max_length, - C.precision, - C.scale, - C.is_nullable, - C.is_identity - INTO #Actual FROM $(FacadeTargetDb).sys.columns AS C WHERE C.object_id = OBJECT_ID('$(FacadeTargetDb).dbo.SomeOtherTable'); - - SELECT - C.name, - C.column_id, - C.system_type_id, - C.user_type_id, - C.max_length, - C.precision, - C.scale, - C.is_nullable, - C.is_identity - INTO #Expected FROM sys.columns AS C WHERE C.object_id = @TableObjectId; - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; - -END; -GO - -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacade creates a facade table for a view in the facade db] -AS -BEGIN - EXEC ('CREATE VIEW dbo.SomeRandomView AS SELECT CAST(1 AS INT) columnNameA;'); - - DECLARE @TableObjectId INT = OBJECT_ID('dbo.SomeRandomView'); - - EXEC Facade.CreateTableFacade @FacadeDbName = '$(FacadeTargetDb)', @TableObjectId = @TableObjectId; - - SELECT 'Is a table.' AS resultColumn INTO #Actual - FROM $(FacadeTargetDb).sys.tables T - JOIN $(FacadeTargetDb).sys.schemas S ON (T.schema_id = S.schema_id) - WHERE T.name = 'SomeRandomView' AND S.name = 'dbo'; - - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - - INSERT INTO #Expected VALUES ('Is a table.'); - - EXEC tSQLt.AssertEqualsTable @Expected = N'#Expected', @Actual = N'#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacades doesn't call CreateTableFacade if there are no tables] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - - EXEC Facade.CreateTableFacades @FacadeDbName = '$(FacadeTargetDb)'; - - EXEC tSQLt.AssertEmptyTable @TableName = 'Facade.[CreateTableFacade_SpyProcedureLog]'; -END; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacades calls CreateTableFacade for single table] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomTable'');'); - - EXEC Facade.CreateTableFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT TableObjectId INTO #Actual FROM Facade.[CreateTableFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacades calls CreateTableFacade for multiple tables] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1003,SCHEMA_ID(''tSQLt''),''cRandomTable'');'); - - EXEC Facade.CreateTableFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT TableObjectId INTO #Actual FROM Facade.[CreateTableFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1002),(1003); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacades calls CreateTableFacade only for tables which are not Private] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1002,SCHEMA_ID(''tSQLt''),''PrivateRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1003,SCHEMA_ID(''tSQLt''),''PrIVateRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1004,SCHEMA_ID(''tSQLt''),''PRIVATERandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1005,SCHEMA_ID(''tSQLt''),''cRandomTable'');'); - - EXEC Facade.CreateTableFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT TableObjectId INTO #Actual FROM Facade.[CreateTableFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1005); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacades calls CreateTableFacade only for tables which are in the tSQLt schema] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomTable'');'); - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name) VALUES (1003,SCHEMA_ID(''dbo''),''cRandomTable'');'); - - EXEC Facade.CreateTableFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT TableObjectId INTO #Actual FROM Facade.[CreateTableFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1002); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacade works for table names with single quote] -AS -BEGIN - CREATE TABLE dbo.[SomeR'andomTable] (a INT); - - DECLARE @TableObjectId INT = OBJECT_ID('dbo.[SomeR''andomTable]'); - - EXEC Facade.CreateTableFacade @FacadeDbName = '$(FacadeTargetDb)', @TableObjectId = @TableObjectId; - - EXEC tSQLt.AssertObjectExists @ObjectName = '$(FacadeTargetDb).dbo.[SomeR''andomTable]'; - -END; -GO -CREATE PROCEDURE Facade_CreateTableFacades_Tests.[test CreateTableFacades passes @FacadeDbName to CreateTableFacade] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateTableFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.tables](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''AProc'');'); - - EXEC Facade.CreateTableFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName INTO #Actual FROM Facade.[CreateTableFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)'); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO diff --git a/FacadeTests/Facade_CreateViewFacades_Tests.class.sql b/FacadeTests/Facade_CreateViewFacades_Tests.class.sql deleted file mode 100644 index 319cf2742..000000000 --- a/FacadeTests/Facade_CreateViewFacades_Tests.class.sql +++ /dev/null @@ -1,174 +0,0 @@ -:SETVAR FacadeTargetDb tSQLtFacade ----Build+ -GO -EXEC tSQLt.NewTestClass 'Facade_CreateViewFacades_Tests'; -GO -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacade copies a simple view to the facade db] -AS -BEGIN - EXEC ('CREATE VIEW dbo.SomeRandomView AS SELECT CAST(1 AS INT) a;'); - DECLARE @ViewObjectId INT = OBJECT_ID('dbo.SomeRandomView'); - - EXEC Facade.CreateViewFacade @FacadeDbName = '$(FacadeTargetDb)', @ViewObjectId = @ViewObjectId; - - EXEC tSQLt.AssertObjectExists @ObjectName = '$(FacadeTargetDb).dbo.SomeRandomView'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacade copies another view to the facade db with all columns] -AS -BEGIN - EXEC ('CREATE VIEW dbo.SomeOtherRandomView AS SELECT CAST(1 AS INT) a, CAST(NULL AS DATETIME) b, CAST(1.1 as NUMERIC(13,10)) c;'); - DECLARE @ViewObjectId INT = OBJECT_ID('dbo.SomeOtherRandomView'); - - EXEC Facade.CreateViewFacade @FacadeDbName = '$(FacadeTargetDb)', @ViewObjectId = @ViewObjectId; - - SELECT - C.name, - C.column_id, - C.system_type_id, - C.user_type_id, - C.max_length, - C.precision, - C.scale, - C.is_nullable, - C.is_identity - INTO #Actual FROM $(FacadeTargetDb).sys.columns AS C WHERE C.object_id = OBJECT_ID('$(FacadeTargetDb).dbo.SomeOtherRandomView'); - - SELECT - C.name, - C.column_id, - C.system_type_id, - C.user_type_id, - C.max_length, - C.precision, - C.scale, - C.is_nullable, - C.is_identity - INTO #Expected FROM sys.columns AS C WHERE C.object_id = @ViewObjectId; - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacade copies view into a schema that does not exist in the facade db] -AS -BEGIN - DECLARE @SchemaName NVARCHAR(MAX) = 'SomeRandomSchema'+CONVERT(NVARCHAR(MAX),CAST(NEWID() AS VARBINARY(MAX)),2); - DECLARE @cmd NVARCHAR(MAX); - - SET @cmd = 'CREATE SCHEMA '+@SchemaName+';'; - EXEC(@cmd); - - SET @cmd = 'CREATE VIEW ' + @SchemaName + '.SomeRandomView AS SELECT CAST(1 AS INT) a;'; - EXEC(@cmd); - - DECLARE @ViewObjectId INT = OBJECT_ID(@SchemaName+'.SomeRandomView'); - - EXEC Facade.CreateViewFacade @FacadeDbName = '$(FacadeTargetDb)', @ViewObjectId = @ViewObjectId; - - DECLARE @RemoteObjectName NVARCHAR(MAX) = '$(FacadeTargetDb).'+@SchemaName+'.SomeRandomView'; - EXEC tSQLt.AssertObjectExists @ObjectName = @RemoteObjectName; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacades doesn't call CreateViewFacade if there are no views] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - - EXEC Facade.CreateViewFacades @FacadeDbName = '$(FacadeTargetDb)'; - - EXEC tSQLt.AssertEmptyTable @TableName = 'Facade.[CreateViewFacade_SpyProcedureLog]'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacades calls CreateViewFacade for single view] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name)VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomView'');'); - - EXEC Facade.CreateViewFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName,ViewObjectId INTO #Actual FROM Facade.[CreateViewFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 1001); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacades calls CreateViewFacade for multiple views] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1003,SCHEMA_ID(''tSQLt''),''cRandomView'');'); - - EXEC Facade.CreateViewFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT FacadeDbName,ViewObjectId INTO #Actual FROM Facade.[CreateViewFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES('$(FacadeTargetDb)', 1001),('$(FacadeTargetDb)', 1002),('$(FacadeTargetDb)', 1003); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacades calls CreateViewFacade only for views which are not Private] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1002,SCHEMA_ID(''tSQLt''),''PrivateRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1003,SCHEMA_ID(''tSQLt''),''PrIVateRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1004,SCHEMA_ID(''tSQLt''),''PRIVATERandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1005,SCHEMA_ID(''tSQLt''),''cRandomView'');'); - - EXEC Facade.CreateViewFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT ViewObjectId INTO #Actual FROM Facade.[CreateViewFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1005); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacades calls CreateViewFacade only for views which are in the tSQLt schema] -AS -BEGIN - EXEC tSQLt.SpyProcedure @ProcedureName = 'Facade.CreateViewFacade'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.tables]'; - EXEC tSQLt.FakeTable @TableName = 'Facade.[sys.views]'; - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1001,SCHEMA_ID(''tSQLt''),''aRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1002,SCHEMA_ID(''tSQLt''),''bRandomView'');'); - EXEC('INSERT INTO Facade.[sys.views](object_id,schema_id,name) VALUES (1003,SCHEMA_ID(''dbo''),''cRandomView'');'); - - EXEC Facade.CreateViewFacades @FacadeDbName = '$(FacadeTargetDb)'; - - SELECT ViewObjectId INTO #Actual FROM Facade.[CreateViewFacade_SpyProcedureLog]; - SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; - INSERT INTO #Expected - VALUES(1001),(1002); - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - -CREATE PROCEDURE Facade_CreateViewFacades_Tests.[test CreateViewFacade works for view names with single quote] -AS -BEGIN - EXEC ('CREATE VIEW dbo.[SomeRa''ndomView] AS SELECT CAST(1 AS INT) a;'); - DECLARE @ViewObjectId INT = OBJECT_ID('dbo.[SomeRa''ndomView]'); - - EXEC Facade.CreateViewFacade @FacadeDbName = '$(FacadeTargetDb)', @ViewObjectId = @ViewObjectId; - - EXEC tSQLt.AssertObjectExists @ObjectName = '$(FacadeTargetDb).dbo.[SomeRa''ndomView]'; -END; -GO diff --git a/FacadeTests/Facade_Dacpac_Tests.class.sql b/FacadeTests/Facade_Dacpac_Tests.class.sql deleted file mode 100644 index 0977a7dd3..000000000 --- a/FacadeTests/Facade_Dacpac_Tests.class.sql +++ /dev/null @@ -1,80 +0,0 @@ -:SETVAR DacpacTargetDb tSQLt_dacpac ----Build+ -GO -EXEC tSQLt.NewTestClass 'Facade_Dacpac_Tests'; -GO -CREATE PROCEDURE Facade_Dacpac_Tests.[test dacpac contains all objects] -AS -BEGIN - SELECT O.name, CASE WHEN O.type_desc LIKE '%STORED[_]PROCEDURE' THEN 'STORED_PROCEDURE' ELSE O.type_desc END type_desc - INTO #Expected - FROM sys.objects O - WHERE O.schema_id = SCHEMA_ID('tSQLt') - AND UPPER(O.name) NOT LIKE 'PRIVATE%' - AND O.type NOT IN ('D', 'PK','UQ') - - SELECT O.name, CASE WHEN O.type_desc LIKE '%STORED[_]PROCEDURE' THEN 'STORED_PROCEDURE' ELSE O.type_desc END type_desc - INTO #Actual - FROM $(DacpacTargetDb).sys.objects O - WHERE O.schema_id = SCHEMA_ID('tSQLt') - AND UPPER(O.name) NOT LIKE 'PRIVATE%' - AND O.type NOT IN ('D', 'PK','UQ') - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO -CREATE PROCEDURE Facade_Dacpac_Tests.[test dacpac contains all tSQLt users] -AS -BEGIN - SELECT SDP.name, SDP.type_desc - INTO #Expected - FROM sys.database_principals SDP - WHERE UPPER(SDP.name) LIKE ('%TSQLT%') - - SELECT SDP.name, SDP.type_desc - INTO #Actual - FROM $(DacpacTargetDb).sys.database_principals SDP - WHERE UPPER(SDP.name) LIKE ('%TSQLT%') - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO --- TODO: If we recommit to facades, we should ensure that the authentication_type_desc is in ('NONE','DATABASE') in the Facade_CreateFacadeDb_Tests and then enable and fix the test below. --- CREATE PROCEDURE Facade_Dacpac_Tests.[test dacpac contains all tSQLt users for SQL Server 2012 (11.x) and later] --- AS --- BEGIN --- SELECT SDP.name, SDP.type_desc, SDP.authentication_type_desc --- INTO #Expected --- FROM sys.database_principals SDP --- WHERE UPPER(SDP.name) LIKE ('%TSQLT%') - --- SELECT SDP.name, SDP.type_desc, SDP.authentication_type_desc --- INTO #Actual --- FROM $(DacpacTargetDb).sys.database_principals SDP --- WHERE UPPER(SDP.name) LIKE ('%TSQLT%') - --- EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; --- END; --- GO -CREATE PROCEDURE Facade_Dacpac_Tests.[test dacpac contains all tSQLt datatypes] -AS -BEGIN - SELECT ST.name - INTO #Expected - FROM sys.types ST - WHERE ST.schema_id = SCHEMA_ID('tSQLt') - AND UPPER(ST.name) NOT LIKE 'PRIVATE%' - - SELECT ST.name - INTO #Actual - FROM $(DacpacTargetDb).sys.types ST - WHERE ST.schema_id = SCHEMA_ID('tSQLt') - AND UPPER(ST.name) NOT LIKE 'PRIVATE%' - - EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; -END; -GO - - - - diff --git a/FacadeTests/buildFacadeTests.ps1 b/FacadeTests/buildFacadeTests.ps1 deleted file mode 100644 index 7752e63d0..000000000 --- a/FacadeTests/buildFacadeTests.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -Push-Location; - -$scriptpath = $MyInvocation.MyCommand.Path; -$dir = Split-Path $scriptpath; -#Log-Output "FileLocation: $dir"; -Set-Location $dir; - -../Build/BuildHelper.exe "*.class.sql" "../Build/temp/tSQLtBuild/Facade/FacadeTests.sql" "---Build" - -$executeFacadeTests = @" - :r FacadeScript.sql - GO - :r FacadeTests.sql - GO -"@; - -Set-Content "../Build/temp/tSQLtBuild/Facade/DeployFacadeTests.sql" $executeFacadeTests; - -Pop-Location; \ No newline at end of file diff --git a/PADGen/sqlitynet/pad_tsqlt.xml b/PADGen/sqlitynet/pad_tsqlt.xml deleted file mode 100644 index de2d581b3..000000000 --- a/PADGen/sqlitynet/pad_tsqlt.xml +++ /dev/null @@ -1,216 +0,0 @@ - - - - 3.11 - PADGen 3.1.1.47 http://www.padgen.org - Portable Application Description, or PAD for short, is a data set that is used by shareware authors to disseminate information to anyone interested in their software products. To find out more go to http://pad.asp-software.org - - - sqlity.net - - - Malvern - PA - - USA - http://sqlity.net - - tSQLt - sqlity.net - tsqlt@sqlity.net - tsqlt - sqlity - tsqlt@sqlity.net - - - tsqlt@googlegroups.com - tsqlt@googlegroups.com - tsqlt@googlegroups.com - - - - - - - - tSQLt - 7 - 05 - 23 - 2010 - - - - Freeware - New Release - - Not Applicable - English - - Development Tools - Development::Other - MS SQL Server 2005+ - - 17500 - 17 - 0.02 - - - N - - Days - - - - - - - - - t-sql, unit testing, SQL-Server, TDD, Database TDD, Test Driven Development, SQL - t-sql unit testing framework - t-sql unit testing framework with support for dependency isolation - tSQLt provides the ability to write unit tests for Microsoft SQL Server T-SQL code. Unlike other frameworks it allows the developer to isolate the unit being tested. For example, it can fake tables or views, spy procedures and test constraints. - tSQLt provides the ability to write unit tests for Microsoft SQL Server T-SQL code. Unlike other frameworks it allows the developer to isolate the unit being tested. For example, it can fake tables or views, spy procedures and test constraints. - - What is tSQLt? -tSQLt is a unit testing framework for Microsoft SQL Server. tSQLt is compatible with SQL Server 2005 and above on all editions. - -- Main Features -tSQLt allows you to implement unit tests in T-SQL. This is important as you do not have to switch between various tools to create your code and your unit tests. tSQLt also provides the following features to make it easier to create and manage unit tests: -Tests are automatically run within transactions - this keeps tests independent and reduces any cleanup work you need -Tests can be grouped together within a schema - allowing you to organize your tests and use common setup methods -Output can be generated in plain text or XML - making it easier to integrate with a continuous integration tool -Provides the ability to fake tables and views, and to create stored procedure spies - allowing you to isolate the code which you are testing - - - - - http://tsqlt.org - - - - - - - http://sourceforge.net/projects/tsqlt/ - - - - - - - - - - - Y - 1.4 - http://pad.asp-software.org/extensions/Affiliates.htm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Y - N - - - diff --git a/PADGen/sqlitynet/sqlitynet.cml b/PADGen/sqlitynet/sqlitynet.cml deleted file mode 100644 index 3a728340a..000000000 --- a/PADGen/sqlitynet/sqlitynet.cml +++ /dev/null @@ -1,31 +0,0 @@ - - - PADGen 3.1.1.47 - - sqlity.net - - - Malvern - PA - - USA - http://sqlity.net - - tSQLt - sqlity.net - tsqlt@sqlity.net - tsqlt - sqlity - tsqlt@sqlity.net - - - tsqlt@googlegroups.com - tsqlt@googlegroups.com - tsqlt@googlegroups.com - - - - - - - diff --git a/PADGen/sqlitynet/tsqlt.pml b/PADGen/sqlitynet/tsqlt.pml deleted file mode 100644 index 3c0dd284f..000000000 --- a/PADGen/sqlitynet/tsqlt.pml +++ /dev/null @@ -1,186 +0,0 @@ - - - PADGen 3.1.1.47 - - - tSQLt - 7 - 05 - 23 - 2010 - - - - Freeware - New Release - - Not Applicable - English - - Development Tools - Development::Other - MS SQL Server 2005+ - - 17500 - 17 - 0.02 - - - N - - Days - - - - - - - - - t-sql, unit testing, SQL-Server, TDD, Database TDD, Test Driven Development, SQL - t-sql unit testing framework - t-sql unit testing framework with support for dependency isolation - tSQLt provides the ability to write unit tests for Microsoft SQL Server T-SQL code. Unlike other frameworks it allows the developer to isolate the unit being tested. For example, it can fake tables or views, spy procedures and test constraints. - tSQLt provides the ability to write unit tests for Microsoft SQL Server T-SQL code. Unlike other frameworks it allows the developer to isolate the unit being tested. For example, it can fake tables or views, spy procedures and test constraints. - - What is tSQLt? -tSQLt is a unit testing framework for Microsoft SQL Server. tSQLt is compatible with SQL Server 2005 and above on all editions. - -- Main Features -tSQLt allows you to implement unit tests in T-SQL. This is important as you do not have to switch between various tools to create your code and your unit tests. tSQLt also provides the following features to make it easier to create and manage unit tests: -Tests are automatically run within transactions - this keeps tests independent and reduces any cleanup work you need -Tests can be grouped together within a schema - allowing you to organize your tests and use common setup methods -Output can be generated in plain text or XML - making it easier to integrate with a continuous integration tool -Provides the ability to fake tables and views, and to create stored procedure spies - allowing you to isolate the code which you are testing - - - - - http://tsqlt.org - - - - - - - http://sourceforge.net/projects/tsqlt/ - - - - - - - - - - - Y - 1.4 - http://pad.asp-software.org/extensions/Affiliates.htm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Y - N - - - diff --git a/README.md b/README.md index 54d1784b3..cd477cb9f 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,5 @@ tSQLt allows you to implement unit tests in T-SQL. This is important as you do n * Output can be generated in plain text or XML – making it easier to integrate with a continuous integration tool tSQLt is licensed under Apache 2.0 (https://github.com/tSQLt-org/tSQLt/blob/master/Build/License.txt) + + diff --git a/Source/BuildOrder.txt b/Source/BuildOrder.txt index fde19de14..438bff8a6 100644 --- a/Source/BuildOrder.txt +++ b/Source/BuildOrder.txt @@ -34,6 +34,12 @@ tSQLt.LogCapturedOutput.ssp.sql ../Build/temp/tSQLtBuild/CreateAssembly.sql tSQLtCLR_CreateProcs.sql tSQLt.Private_PrepareFakeFunctionOutputTable.ssp.sql +tSQLt.Private_TableToTextColumnListAdjustWidth.sfn.sql +tSQLt.Private_TableToTextColumnListMaxLenNumbered.sfn.sql +tSQLt.Private_TableToTextColumnListQuotedAndNumbered.sfn.sql +tSQLt.Private_TableToTextColumnListSeparatorLine.sfn.sql +tSQLt.Private_TableToTextColumntoStringList.sfn.sql +tSQLt.Private_TableToTextNumberedColumnsWithSeparator.sfn.sql tSQLt.TableToText.ssp.sql tSQLt.Private_RenamedObjectLog.tbl.sql tSQLt.Private_RenameObject.ssp.sql diff --git a/Source/PrepareServerBuildOrder.txt b/Source/PrepareServerBuildOrder.txt index fcf3e1e09..8fcc0f403 100644 --- a/Source/PrepareServerBuildOrder.txt +++ b/Source/PrepareServerBuildOrder.txt @@ -1,4 +1,4 @@ -../Build/temp/tSQLtBuild/tSQLt.Private_GetAssemblyKeyBytes.sql +../Build/temp/tSQLtBuild/tSQLt.Private_GetAssemblyKeyBytes.sql tSQLt.Private_EnableCLR.ssp.sql tSQLt.Private_GetSQLProductMajorVersion.ssp.sql tSQLt.RemoveAssemblyKey.ssp.sql diff --git a/Source/ResetValidationServerBuildOrder.txt b/Source/ResetValidationServerBuildOrder.txt deleted file mode 100644 index dad7ec254..000000000 --- a/Source/ResetValidationServerBuildOrder.txt +++ /dev/null @@ -1,4 +0,0 @@ -../Build/temp/tSQLtBuild/tSQLt.Private_GetAssemblyKeyBytes.sql -tSQLt.Private_GetSQLProductMajorVersion.ssp.sql -tSQLt.RemoveAssemblyKey.ssp.sql -../Build/ExecuteResetValidationServer.sql diff --git a/Source/ResetValidationServerBuildOrder1.txt b/Source/ResetValidationServerBuildOrder1.txt new file mode 100644 index 000000000..f42378a65 --- /dev/null +++ b/Source/ResetValidationServerBuildOrder1.txt @@ -0,0 +1,4 @@ +../Build/temp/tSQLtTests/Source/tSQLt.Private_GetAssemblyKeyBytes.sql +tSQLt.Private_GetSQLProductMajorVersion.ssp.sql +tSQLt.RemoveAssemblyKey.ssp.sql +../Build/SQL/ExecuteResetValidationServer.sql diff --git a/Source/ResetValidationServerBuildOrder2.txt b/Source/ResetValidationServerBuildOrder2.txt new file mode 100644 index 000000000..907d67995 --- /dev/null +++ b/Source/ResetValidationServerBuildOrder2.txt @@ -0,0 +1,3 @@ +../Build/temp/tSQLtTests/ResetValidationServer.tmp.sql +../Build/SQL/ForceDropTempProcedures.sql +../Build/SQL/CreateLogin(tSQLt.Build).sql \ No newline at end of file diff --git a/Source/Source.sqlproj b/Source/Source.sqlproj new file mode 100644 index 000000000..93e598a47 --- /dev/null +++ b/Source/Source.sqlproj @@ -0,0 +1,13 @@ + + + + + Source + {57B28F7E-3312-4E55-A6FA-75019BDACA5B} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Source/Source.ssmssqlproj b/Source/Source.ssmssqlproj deleted file mode 100644 index 16b62a88c..000000000 --- a/Source/Source.ssmssqlproj +++ /dev/null @@ -1,790 +0,0 @@ - - - - - - - - - - - - - ApplyConstraint_Methods.sql - - - - - - ExecutePrepareServer.sql - - - - - - Run_Methods.sql - - - - - - tSQLt.(at)tSQLt_MaxSqlMajorVersion.sfn.sql - - - - - - tSQLt.(at)tSQLt_MinSqlMajorVersion.sfn.sql - - - - - - tSQLt.(at)tSQLt_NoTransaction.sfn.sql - - - - - - tSQLt.(at)tSQLt_RunOnlyOnHostPlatform.sfn.sql - - - - - - tSQLt.(at)tSQLt_SkipTest.sfn.sql - - - - - - tSQLt.ApplyTrigger.ssp.sql - - - - - - tSQLt.AssertEmptyTable.ssp.sql - - - - - - tSQLt.AssertEqualsString.ssp.sql - - - - - - tSQLt.AssertEqualsTable.ssp.sql - - - - - - tSQLt.AssertEqualsTableSchema.ssp.sql - - - - - - tSQLt.AssertLike.ssp.sql - - - - - - tSQLt.AssertNotEquals.ssp.sql - - - - - - tSQLt.AssertObjectDoesNotExist.ssp.sql - - - - - - tSQLt.AssertObjectExists.ssp.sql - - - - - - tSQLt.AssertStringIn.ssp.sql - - - - - - tSQLt.AssertStringTable.udt.sql - - - - - - tSQLt.CaptureOutputLog.tbl.sql - - - - - - tSQLt.DropClass.ssp.sql - - - - - - tSQLt.EnableExternalAccess.ssp.sql - - - - - - tSQLt.ExpectException.ssp.sql - - - - - - tSQLt.ExpectNoException.ssp.sql - - - - - - tSQLt.Fail.ssp.sql - - - - - - tSQLt.FakeFunction.ssp.sql - - - - - - tSQLt.FakeTable.ssp.sql - - - - - - tSQLt.FriendlySQLServerVersion.sfn.sql - - - - - - tSQLt.Info.sfn.sql - - - - - - tSQLt.InstallAssemblyKey.ssp.sql - - - - - - tSQLt.InstallExternalAccessKey.ssp.sql - - - - - - tSQLt.LogCapturedOutput.ssp.sql - - - - - - tSQLt.NewTestClass.ssp.sql - - - - - - tSQLt.PrepareServer.ssp.sql - - - - - - tSQLt.Private_AssertNoSideEffects.ssp.sql - - - - - - tSQLt.Private_AssertNoSideEffects_GenerateCommand.sfn.sql - - - - - - tSQLt.Private_CleanTestResult.ssp.sql - - - - - - tSQLt.Private_CleanUp.ssp.sql - - - - - - tSQLt.Private_CleanUpCmdHandler.ssp.sql - - - - - - tSQLt.Private_CompareTables.ssp.sql - - - - - - tSQLt.Private_CompareTablesFailIfUnequalRowsExists.ssp.sql - - - - - - tSQLt.Private_Configurations.tbl.sql - - - - - - tSQLt.Private_CreateFakeFunction.ssp.sql - - - - - - tSQLt.Private_CreateFakeFunctionStatement.sfn.sql - - - - - - tSQLt.Private_CreateFakeOfTable.ssp.sql - - - - - - tSQLt.Private_CreateFakeTableStatement.sfn.sql - - - - - - tSQLt.Private_CreateProcedureSpy.ssp.sql - - - - - - tSQLt.Private_CreateResultTableForCompareTables.ssp.sql - - - - - - tSQLt.Private_DisallowOverwritingNonTestSchema.ssp.sql - - - - - - tSQLt.Private_EnableCLR.ssp.sql - - - - - - tSQLt.Private_GenerateCreateProcedureSpyStatement.ssp.sql - - - - - - tSQLt.Private_GetAssemblyKeyBytes.mdl.sql - - - - - - tSQLt.Private_GetCommaSeparatedColumnList.sfn.sql - - - - - - tSQLt.Private_GetConfiguration.sfn.sql - - - - - - tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql - - - - - - tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql - - - - - - tSQLt.Private_GetDropItemCmd.sfn.sql - - - - - - tSQLt.Private_GetForeignKeyDefinition.sfn.sql - - - - - - tSQLt.Private_GetFormattedErrorInfo.sfn.sql - - - - - - tSQLt.Private_GetFullTypeName.sfn.sql - - - - - - tSQLt.Private_GetIdentityDefinition.sfn.sql - - - - - - tSQLt.Private_GetSQLProductMajorVersion.ssp.sql - - - - - - tSQLt.Private_GetUniqueConstraintDefinition.sfn.sql - - - - - - tSQLt.Private_HandleMessageAndResult.sfn.sql - - - - - - tSQLt.Private_HostPlatform.stub.sql - - - - - - tSQLt.Private_HostPlatform.svw.sql - - - - - - tSQLt.Private_Init.ssp.sql - - - - - - tSQLt.Private_InstallationInfo.sfn.sql - - - - - - tSQLt.Private_InstallationInfo.stub.sql - - - - - - tSQLt.Private_ListTestAnnotations.sfn.sql - - - - - - tSQLt.Private_Lock.tbl.sql - - - - - - tSQLt.Private_MarktSQLtTempObject.ssp.sql - - - - - - tSQLt.Private_MarkObjectBeforeRename.ssp.sql - - - - - - tSQLt.Private_MarkSchemaAsTestClass.ssp.sql - - - - - - tSQLt.Private_NewTestClassList.tbl.sql - - - - - - tSQLt.Private_NoTransactionHandleTable.ssp.sql - - - - - - tSQLt.Private_NoTransactionTableAction.view.sql - - - - - - tSQLt.Private_NoTransactionHandleTables.ssp.sql - - - - - - tSQLt.Private_PrepareFakeFunctionOutputTable.ssp.sql - - - - - - tSQLt.Private_ProcessTestAnnotations.ssp.sql - - - - - - tSQLt.Private_QuoteClassNameForNewTestClass.sfn.sql - - - - - - tSQLt.Private_RemoveSchemaBinding.ssp.sql - - - - - - tSQLt.Private_RemoveSchemaBoundReferences.ssp.sql - - - - - - tSQLt.Private_RenameObject.ssp.sql - - - - - - tSQLt.Private_RenameObjectToUniqueName.ssp.sql - - - - - - tSQLt.Private_RenameObjectToUniqueNameUsingObjectId.ssp.sql - - - - - - tSQLt.Private_RenamedObjectLog.tbl.sql - - - - - - tSQLt.Private_ResetNewTestClassList.ssp.sql - - - - - - tSQLt.Private_Results.view.sql - - - - - - tSQLt.Private_ScriptIndex.sfn.sql - - - - - - tSQLt.Private_Seize.tbl.sql - - - - - - tSQLt.Private_SetConfiguration.ssp.sql - - - - - - tSQLt.Private_SkipTestAnnotationHelper.ssp.sql - - - - - - tSQLt.Private_SplitSqlVersion.sfn.sql - - - - - - tSQLt.Private_SqlVariantFormatter.sfn.sql - - - - - - tSQLt.Private_SqlVersion.sfn.sql - - - - - - tSQLt.Private_SysIndexes.svw.sql - - - - - - tSQLt.Private_SysTypes.svw.sql - - - - - - tSQLt.Private_UndoSingleTestDouble.ssp.sql - - - - - - tSQLt.Private_ValidateFakeTableParameters.ssp.sql - - - - - - tSQLt.Private_ValidateObjectsCompatibleWithFakeFunction.ssp.sql - - - - - - tSQLt.Private_ValidateProcedureCanBeUsedWithSpyProcedure.ssp.sql - - - - - - tSQLt.Private_ValidateThatAllDataTypesInTableAreSupported.ssp.sql - - - - - - tSQLt.RemoveAssemblyKey.ssp.sql - - - - - - tSQLt.RemoveExternalAccessKey.ssp.sql - - - - - - tSQLt.RemoveObject.ssp.sql - - - - - - tSQLt.RemoveObjectIfExists.ssp.sql - - - - - - tSQLt.RenameClass.ssp.sql - - - - - - tSQLt.Reset.ssp.sql - - - - - - tSQLt.schema.sql - - - - - - tSQLt.SetSummaryError.ssp.sql - - - - - - tSQLt.SetVerbose.ssp.sql - - - - - - tSQLt.SpyProcedure.ssp.sql - - - - - - tSQLt.StubRecord.ssp.sql - - - - - - tSQLt.TableToText.ssp.sql - - - - - - tSQLt._Footer.sql - - - - - - tSQLt._Header.sql - - - - - - tSQLt.class.sql - - - - - - tSQLt.TestClass.user.sql - - - - - - tSQLt.TestClasses.view.sql - - - - - - tSQLt.Tests.view.sql - - - - - - tSQLt.UndoTestDoubles.ssp.sql - - - - - - tSQLt.Uninstall.ssp.sql - - - - - - tSQLtCLR.mdl.sql - - - - - - tSQLtCLR_CreateProcs.sql - - - - - - - - - - BuildOrder.txt - - - - - - PrepareServerBuildOrder.txt - - - - - - ResetValidationServerBuildOrder.txt - - - - - - tSQLtDropBuildOrder.txt - - - - - \ No newline at end of file diff --git a/Source/tSQLt.DropClass.ssp.sql b/Source/tSQLt.DropClass.ssp.sql index 86c8ce058..a2b181229 100644 --- a/Source/tSQLt.DropClass.ssp.sql +++ b/Source/tSQLt.DropClass.ssp.sql @@ -80,7 +80,7 @@ BEGIN FROM StatementBlob; EXEC(@Cmd); -END; /*SnipEnd: CreateDropClassStatement.ps1*/ +END; ---Build- GO diff --git a/Source/tSQLt.FriendlySQLServerVersion.sfn.sql b/Source/tSQLt.FriendlySQLServerVersion.sfn.sql index 588222bbd..052051a0c 100644 --- a/Source/tSQLt.FriendlySQLServerVersion.sfn.sql +++ b/Source/tSQLt.FriendlySQLServerVersion.sfn.sql @@ -12,6 +12,7 @@ RETURN SELECT @ProductVersion ProductVersion, CASE + WHEN SSV.Major = '16' THEN '2022' WHEN SSV.Major = '15' THEN '2019' WHEN SSV.Major = '14' THEN '2017' WHEN SSV.Major = '13' THEN '2016' diff --git a/Source/tSQLt.Private_GetSQLProductMajorVersion.ssp.sql b/Source/tSQLt.Private_GetSQLProductMajorVersion.ssp.sql index 5fe2dd083..d508a9de0 100644 --- a/Source/tSQLt.Private_GetSQLProductMajorVersion.ssp.sql +++ b/Source/tSQLt.Private_GetSQLProductMajorVersion.ssp.sql @@ -10,5 +10,5 @@ GO GO DECLARE @Version INT; EXEC @Version = tSQLt.Private_GetSQLProductMajorVersion; -PRINT @Version; +PRINT 'SQL Major Version: '+CAST(@Version as NVARCHAR(MAX)); diff --git a/Source/tSQLt.Private_TableToTextColumnListAdjustWidth.sfn.sql b/Source/tSQLt.Private_TableToTextColumnListAdjustWidth.sfn.sql new file mode 100644 index 000000000..40ddccd5d --- /dev/null +++ b/Source/tSQLt.Private_TableToTextColumnListAdjustWidth.sfn.sql @@ -0,0 +1,37 @@ +IF OBJECT_ID('tSQLt.Private_TableToTextColumnListAdjustWidth') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListAdjustWidth; +GO +---Build+ +GO +CREATE FUNCTION tSQLt.Private_TableToTextColumnListAdjustWidth( + @tmpObjectId INT +) +RETURNS TABLE +AS +RETURN + SELECT + ( + SELECT + ',C'+NN+' = CASE WHEN LEN(C.C'+NN+')>L.MCW '+ + 'THEN LEFT(C.C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C.C'+NN+',(L.MCW-5)/2) '+ + 'ELSE LEFT(C.C'+NN+'+REPLICATE('' '','+ + 'CASE WHEN L.MCW < L.L'+NN+' '+ + 'THEN L.MCW ELSE L.L'+NN+' END - '+ + 'LEN(C.C'+NN+')),'+ + 'CASE WHEN L.MCW < L.L'+NN+' '+ + 'THEN L.MCW ELSE L.L'+NN+' END) '+ + 'END' + FROM( + SELECT + column_id,RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) NN + FROM sys.columns + WHERE object_id = @tmpObjectId + AND column_id>1 + )X + ORDER BY column_id + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') [ColumnList]; + GO +---Build- +GO +--+REPLICATE(' ',LEN(C'+NN+')) +--',C'+NN+' = CASE WHEN LEN(C'+NN+')>L.MCW THEN LEFT(C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C'+NN+',(L.MCW-5)/2) ELSE LEFT(C'+NN+'+REPLICATE(' ',CASE WHEN L.MCW < L.L'+NN+' THEN L.MCW ELSE L.L'+NN+' END - LEN(C'+NN+')),9) END' \ No newline at end of file diff --git a/Source/tSQLt.Private_TableToTextColumnListMaxLenNumbered.sfn.sql b/Source/tSQLt.Private_TableToTextColumnListMaxLenNumbered.sfn.sql new file mode 100644 index 000000000..b99f6bcd1 --- /dev/null +++ b/Source/tSQLt.Private_TableToTextColumnListMaxLenNumbered.sfn.sql @@ -0,0 +1,26 @@ +IF OBJECT_ID('tSQLt.Private_TableToTextColumnListMaxLenNumbered') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListMaxLenNumbered; +GO +---Build+ +GO +CREATE FUNCTION tSQLt.Private_TableToTextColumnListMaxLenNumbered( + @tmpObjectId INT +) +RETURNS TABLE +AS +RETURN + SELECT + ( + SELECT + ',MAX(LEN(''.''+C'+ + RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4)+ + '+''.''))-2 L'+ + RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) + FROM sys.columns + WHERE object_id = @tmpObjectId + AND column_id>1 + ORDER BY column_id + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') [ColumnList]; + GO +---Build- +GO diff --git a/Source/tSQLt.Private_TableToTextColumnListQuotedAndNumbered.sfn.sql b/Source/tSQLt.Private_TableToTextColumnListQuotedAndNumbered.sfn.sql new file mode 100644 index 000000000..627dc3960 --- /dev/null +++ b/Source/tSQLt.Private_TableToTextColumnListQuotedAndNumbered.sfn.sql @@ -0,0 +1,26 @@ +IF OBJECT_ID('tSQLt.Private_TableToTextColumnListQuotedAndNumbered') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListQuotedAndNumbered; +GO +---Build+ +GO +CREATE FUNCTION tSQLt.Private_TableToTextColumnListQuotedAndNumbered( + @tmpObjectId INT +) +RETURNS TABLE +AS +RETURN + SELECT + ( + SELECT + ',CAST('+ + QUOTENAME(name,'''')+ + ' AS NVARCHAR(MAX)) C'+ + RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) + FROM sys.columns + WHERE object_id = @tmpObjectId + AND column_id>1 + ORDER BY column_id + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') [ColumnList]; + GO +---Build- +GO diff --git a/Source/tSQLt.Private_TableToTextColumnListSeparatorLine.sfn.sql b/Source/tSQLt.Private_TableToTextColumnListSeparatorLine.sfn.sql new file mode 100644 index 000000000..73da3b159 --- /dev/null +++ b/Source/tSQLt.Private_TableToTextColumnListSeparatorLine.sfn.sql @@ -0,0 +1,31 @@ +IF OBJECT_ID('tSQLt.Private_TableToTextColumnListSeparatorLine') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListSeparatorLine; +GO +---Build+ +GO +CREATE FUNCTION tSQLt.Private_TableToTextColumnListSeparatorLine( + @tmpObjectId INT +) +RETURNS TABLE +AS +RETURN + SELECT + ( + SELECT + ',REPLICATE(''-'','+ + 'CASE WHEN L.MCW < L.L'+NN+' '+ + 'THEN L.MCW ELSE L.L'+NN+' END)' + FROM( + SELECT + column_id,RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) NN + FROM sys.columns + WHERE object_id = @tmpObjectId + AND column_id>1 + )X + ORDER BY column_id + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') [ColumnList]; + GO +---Build- +GO +--+REPLICATE(' ',LEN(C'+NN+')) +--',C'+NN+' = CASE WHEN LEN(C'+NN+')>L.MCW THEN LEFT(C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C'+NN+',(L.MCW-5)/2) ELSE LEFT(C'+NN+'+REPLICATE(' ',CASE WHEN L.MCW < L.L'+NN+' THEN L.MCW ELSE L.L'+NN+' END - LEN(C'+NN+')),9) END' \ No newline at end of file diff --git a/Source/tSQLt.Private_TableToTextColumntoStringList.sfn.sql b/Source/tSQLt.Private_TableToTextColumntoStringList.sfn.sql new file mode 100644 index 000000000..0fabe1bc9 --- /dev/null +++ b/Source/tSQLt.Private_TableToTextColumntoStringList.sfn.sql @@ -0,0 +1,44 @@ +IF OBJECT_ID('tSQLt.Private_TableToTextColumntoStringList') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumntoStringList; +GO +---Build+ +GO +CREATE FUNCTION tSQLt.Private_TableToTextColumntoStringList( + @tmpObjectId INT +) +RETURNS TABLE +AS +RETURN + SELECT + ( + SELECT + ',ISNULL('+ + CASE + WHEN type_name = 'DATETIME' THEN 'CONVERT(NVARCHAR(MAX),'+QUOTENAME(name)+',121)' + WHEN type_name = 'SMALLDATETIME' THEN 'CONVERT(NVARCHAR(16),'+QUOTENAME(name)+',121)' + WHEN type_name = 'FLOAT' THEN 'UPPER(CONVERT(NVARCHAR(MAX),'+QUOTENAME(name)+',2))' + WHEN type_name = 'IMAGE' THEN 'CONVERT(NVARCHAR(MAX),CAST('+QUOTENAME(name)+' AS VARBINARY(MAX)),1)' + WHEN type_name IN ('BINARY','VARBINARY') THEN 'CONVERT(NVARCHAR(MAX),'+QUOTENAME(name)+',1)' + WHEN type_name = 'UNIQUEIDENTIFIER' THEN 'LOWER(CONVERT(NVARCHAR(MAX),'+QUOTENAME(name)+'))' + WHEN type_name = 'TIMESTAMP' THEN 'CONVERT(NVARCHAR(MAX),CAST('+QUOTENAME(name)+' AS VARBINARY(MAX)),1)' + ELSE 'CAST('+QUOTENAME(name)+' AS NVARCHAR(MAX))' + END+ + ',''!NULL!'')' + FROM( + SELECT + C.column_id,UPPER(TS.name) type_name,C.name + FROM sys.columns C + JOIN sys.types TU + ON TU.user_type_id = C.user_type_id + LEFT JOIN sys.types TS + ON TS.user_type_id = TU.system_type_id + WHERE object_id = @tmpObjectId + AND column_id>1 + )X + ORDER BY column_id + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') [ColumnList]; + GO +---Build- +GO +--+REPLICATE(' ',LEN(C'+NN+')) +--',C'+NN+' = CASE WHEN LEN(C'+NN+')>L.MCW THEN LEFT(C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C'+NN+',(L.MCW-5)/2) ELSE LEFT(C'+NN+'+REPLICATE(' ',CASE WHEN L.MCW < L.L'+NN+' THEN L.MCW ELSE L.L'+NN+' END - LEN(C'+NN+')),9) END' \ No newline at end of file diff --git a/Source/tSQLt.Private_TableToTextNumberedColumnsWithSeparator.sfn.sql b/Source/tSQLt.Private_TableToTextNumberedColumnsWithSeparator.sfn.sql new file mode 100644 index 000000000..dd1b54524 --- /dev/null +++ b/Source/tSQLt.Private_TableToTextNumberedColumnsWithSeparator.sfn.sql @@ -0,0 +1,23 @@ +IF OBJECT_ID('tSQLt.Private_TableToTextNumberedColumnsWithSeparator') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextNumberedColumnsWithSeparator; +GO +---Build+ +GO +CREATE FUNCTION tSQLt.Private_TableToTextNumberedColumnsWithSeparator( + @tmpObjectId INT +) +RETURNS TABLE +AS +RETURN + SELECT + ( + SELECT + 'sep+C'+ + RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4)+ + '+' + FROM sys.columns + WHERE object_id = @tmpObjectId + AND column_id>1 + ORDER BY column_id + FOR XML PATH(''),TYPE + ).value('.','NVARCHAR(MAX)') [ColumnList]; + \ No newline at end of file diff --git a/Source/tSQLt.TableToText.ssp.sql b/Source/tSQLt.TableToText.ssp.sql index d0ffecfc5..1342ec2f6 100644 --- a/Source/tSQLt.TableToText.ssp.sql +++ b/Source/tSQLt.TableToText.ssp.sql @@ -9,7 +9,50 @@ CREATE PROCEDURE tSQLt.TableToText @PrintOnlyColumnNameAliasList NVARCHAR(MAX) = NULL AS BEGIN - SET @txt = tSQLt.Private::TableToString(@TableName, @OrderBy, @PrintOnlyColumnNameAliasList); + IF(@TableName IS NULL) + BEGIN + RAISERROR('@TableName cannot be NULL',16,10) + END; + DECLARE @TmpTableName NVARCHAR(MAX) = 'tSQLt.[TableToText.Tmp.'+CAST(NEWID() AS NVARCHAR(MAX))+']'; + IF(OBJECT_ID(@TmpTableName)IS NOT NULL) EXEC('DROP TABLE '+@TmpTableName); + IF(OBJECT_ID('tempdb..[#tSQLt.TableToText.Str]')IS NOT NULL) DROP TABLE [#tSQLt.TableToText.Str]; + IF(OBJECT_ID('tempdb..[#tSQLt.TableToText.Str.Len]')IS NOT NULL) DROP TABLE [#tSQLt.TableToText.Str.Len]; + DECLARE @nl NVARCHAR(MAX) = 'CHAR(13)+CHAR(10)' + DECLARE @MaxColumnWidth INT = 155; + DECLARE @cmd NVARCHAR(MAX)= + 'SET NOCOUNT ON;'+ + 'SELECT * INTO '+@TmpTableName+' FROM (SELECT ROW_NUMBER()OVER(ORDER BY '+ + CASE WHEN NULLIF(LTRIM(@OrderBy),'') IS NULL + THEN '(SELECT 1)' + ELSE @OrderBy + END+')+2 [tSQLt.TableToText.OrderBy],* FROM '+@TableName+')X'+ + -- + CASE WHEN NULLIF(LTRIM(@PrintOnlyColumnNameAliasList),'') IS NULL + THEN '' + ELSE '([tSQLt.TableToText.OrderBy],'+@PrintOnlyColumnNameAliasList+')' + END+';'+ + 'EXEC tSQLt.Private_MarktSQLtTempObject '''+@TmpTableName+''',''TABLE'';'+ + 'DECLARE @tmpObjectId INT = OBJECT_ID('''+@TmpTableName+''');'+ + 'DECLARE @column_list NVARCHAR(MAX) = (SELECT ColumnList FROM tSQLt.Private_TableToTextColumnListQuotedAndNumbered(@tmpObjectId));'+ + 'DECLARE @cmd NVARCHAR(MAX)=''SELECT 1 no,''''|'''' sep''+@column_list+'' INTO [#tSQLt.TableToText.Str];'';'+ + 'SET @column_list = (SELECT ColumnList FROM tSQLt.Private_TableToTextColumntoStringList(@tmpObjectId));'+ + 'SET @cmd = @cmd + ''INSERT INTO [#tSQLt.TableToText.Str] SELECT [tSQLt.TableToText.OrderBy],''''|''''''+@column_list+'' FROM '+@TmpTableName+';'';'+ + 'SET @column_list = (SELECT ColumnList FROM tSQLt.Private_TableToTextColumnListMaxLenNumbered(@tmpObjectId));'+ + 'SET @cmd = @cmd + ''SELECT '+STR(@MaxColumnWidth)+' MCW''+@column_list+'' INTO [#tSQLt.TableToText.Str.Len] FROM [#tSQLt.TableToText.Str];'';'+ + 'SET @column_list = (SELECT ColumnList FROM tSQLt.Private_TableToTextColumnListAdjustWidth(@tmpObjectId));'+ + 'SET @cmd = @cmd + ''WITH LenAdjusted AS ('';'+ + 'SET @cmd = @cmd + ''SELECT no,sep''+@column_list+'' FROM [#tSQLt.TableToText.Str.Len] L CROSS JOIN [#tSQLt.TableToText.Str] C'';'+ + 'SET @cmd = @cmd + '' UNION ALL '';'+ + 'SET @column_list = (SELECT ColumnList FROM tSQLt.Private_TableToTextColumnListSeparatorLine(@tmpObjectId));'+ + 'SET @cmd = @cmd + ''SELECT 2,''''+'''' ''+@column_list+'' FROM [#tSQLt.TableToText.Str.Len] L'';'+ + 'SET @cmd = @cmd + '')'';'+ + 'SET @column_list = (SELECT ColumnList FROM tSQLt.Private_TableToTextNumberedColumnsWithSeparator(@tmpObjectId));'+ + 'SET @cmd = @cmd+''SELECT @txt=STUFF((SELECT '+@nl+'+''+@column_list+''sep FROM LenAdjusted ORDER BY no FOR XML PATH(''''''''),TYPE).value(''''.'''',''''NVARCHAR(MAX)''''),1,2,'''''''');'';'+ + -- 'PRINT @cmd;'+ + 'EXEC sys.sp_executesql @cmd,N''@txt NVARCHAR(MAX) OUT'',@txt OUT;'+ + 'DROP TABLE '+@TmpTableName+';'; + -- PRINT @cmd; + EXEC sys.sp_executesql @cmd,N'@txt NVARCHAR(MAX) OUT',@txt OUT; END; GO ---Build- diff --git a/Source/tSQLt.TempDropStatement.mdl.sql b/Source/tSQLt.TempDropStatement.mdl.sql new file mode 100644 index 000000000..e98e40ff5 --- /dev/null +++ b/Source/tSQLt.TempDropStatement.mdl.sql @@ -0,0 +1,2 @@ +---Build+ +DECLARE @ClassName NVARCHAR(MAX) = 'tSQLt';/*--DROPSTATEMENT--*/ diff --git a/Source/tSQLt._Footer.sql b/Source/tSQLt._Footer.sql index aec93ba60..aebfc8e22 100644 --- a/Source/tSQLt._Footer.sql +++ b/Source/tSQLt._Footer.sql @@ -1,3 +1,4 @@ +---Build-n ---Build+ GO SET NOCOUNT ON; diff --git a/Source/tSQLt._Header.sql b/Source/tSQLt._Header.sql index 9733dd862..69c43ba9a 100644 --- a/Source/tSQLt._Header.sql +++ b/Source/tSQLt._Header.sql @@ -1,3 +1,4 @@ +---Build-h ---Build+ /* Copyright 2011 tSQLt diff --git a/TestUtil/BuildOrder.txt b/TestUtil/BuildOrder.txt index ac9be7dd3..7da4b891e 100644 --- a/TestUtil/BuildOrder.txt +++ b/TestUtil/BuildOrder.txt @@ -1,4 +1,4 @@ tSQLt_testutil.class.sql -../Build/temp/tSQLtBuild/Tests/CreateTestUtilAssembly.sql -../Build/temp/tSQLtBuild/Tests/GetUnsignedEmptyBytes.sql +../Build/temp/tSQLtTests/CreateTestUtilAssembly.sql +../Build/temp/tSQLtTests/GetUnsignedEmptyBytes.sql tSQLtTestUtilCLR_CreateItems.sql diff --git a/TestUtil/TestUtil.sqlproj b/TestUtil/TestUtil.sqlproj new file mode 100644 index 000000000..b42e5cb1f --- /dev/null +++ b/TestUtil/TestUtil.sqlproj @@ -0,0 +1,13 @@ + + + + + TestUtil + {175C322C-24CB-461E-93CD-B47DB6141A87} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/TestUtil/TestUtil.ssmssqlproj b/TestUtil/TestUtil.ssmssqlproj deleted file mode 100644 index cff7ad472..000000000 --- a/TestUtil/TestUtil.ssmssqlproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - GetUnsignedEmptyBytes.mdl.sql - - - - - - SQLQuery1.sql - - - - - - tSQLtTestUtilCLR.mdl.sql - - - - - - tSQLtTestUtilCLR_CreateItems.sql - - - - - - tSQLt_testutil.class.sql - - - - - - - - - - BuildOrder.txt - - - - - \ No newline at end of file diff --git a/TestUtilTests/TestUtilTests.sqlproj b/TestUtilTests/TestUtilTests.sqlproj new file mode 100644 index 000000000..289bd6fb5 --- /dev/null +++ b/TestUtilTests/TestUtilTests.sqlproj @@ -0,0 +1,13 @@ + + + + + TestUtilTests + {89304D64-1E01-4AA2-8A2A-646042F96D81} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/TestUtilTests/TestUtilTests.ssmssqlproj b/TestUtilTests/TestUtilTests.ssmssqlproj deleted file mode 100644 index e07dee1bc..000000000 --- a/TestUtilTests/TestUtilTests.ssmssqlproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - tSQLt_testutil_test.class.sql - - - - - - tSQLt_testutil_test_SA.class.sql - - - - - - - - \ No newline at end of file diff --git a/TestUtilTests/tSQLt_testutil_test.class.sql b/TestUtilTests/tSQLt_testutil_test.class.sql index ef26c9d8d..7035c2fcd 100644 --- a/TestUtilTests/tSQLt_testutil_test.class.sql +++ b/TestUtilTests/tSQLt_testutil_test.class.sql @@ -197,7 +197,7 @@ BEGIN END GO -CREATE PROCEDURE tSQLt_testutil_test.[test DataTypeByteOrdered has constant ToString()] +CREATE PROCEDURE tSQLt_testutil_test.[test DataTypeByteOrdered has ToString()] AS BEGIN DECLARE @inst1 tSQLt_testutil.DataTypeByteOrdered; @@ -205,13 +205,11 @@ BEGIN DECLARE @inst2 tSQLt_testutil.DataTypeByteOrdered; DECLARE @inst2str NVARCHAR(MAX); - SET @inst1 = '1'; - SET @inst2 = '2'; + SET @inst1 = '13'; SET @inst1str = @inst1.ToString(); - SET @inst2str = @inst2.ToString(); - EXEC tSQLt.AssertEqualsString @inst1str,@inst2str; + EXEC tSQLt.AssertEqualsString '<>',@inst1str; END GO CREATE PROCEDURE tSQLt_testutil_test.[test DataTypeByteOrdered has CompareTo (but we can't use it...)] diff --git a/Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.sqlproj b/Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.sqlproj new file mode 100644 index 000000000..0ca6a4b91 --- /dev/null +++ b/Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.sqlproj @@ -0,0 +1,13 @@ + + + + + Tests.EXTERNAL_ACCESS + {F7261171-19E3-441E-9622-9472A4792AE9} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.ssmssqlproj b/Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.ssmssqlproj deleted file mode 100644 index 6b9c0ee75..000000000 --- a/Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.ssmssqlproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - Run_Methods_Tests_EA.class.sql - - - - - - tSQLtclr_test.class.sql - - - - - - - - \ No newline at end of file diff --git a/Tests.EXTERNAL_ACCESS_KEY_EXISTS/EnableExternalAccessTests.class.sql b/Tests.EXTERNAL_ACCESS_KEY_EXISTS/EnableExternalAccessTests.class.sql index cc5aab4e9..63e4b7d54 100644 --- a/Tests.EXTERNAL_ACCESS_KEY_EXISTS/EnableExternalAccessTests.class.sql +++ b/Tests.EXTERNAL_ACCESS_KEY_EXISTS/EnableExternalAccessTests.class.sql @@ -136,10 +136,11 @@ AS BEGIN ALTER ASSEMBLY tSQLtCLR WITH PERMISSION_SET = SAFE; CREATE USER EnableExternalAccessTestsTempUser WITHOUT LOGIN; + GRANT EXECUTE ON tSQLt.EnableExternalAccess TO EnableExternalAccessTestsTempUser; DECLARE @Actual INT; EXECUTE AS USER = 'EnableExternalAccessTestsTempUser'; - EXEC @Actual = tSQLt.EnableExternalAccess @try = 1; + EXEC sys.sp_executesql N'EXEC @Actual = tSQLt.EnableExternalAccess @try = 1;',N'@Actual INT OUT',@Actual OUT; REVERT EXEC tSQLt.AssertEquals -1,@Actual; diff --git a/Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.sqlproj b/Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.sqlproj new file mode 100644 index 000000000..340b83208 --- /dev/null +++ b/Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.sqlproj @@ -0,0 +1,13 @@ + + + + + Tests.EXTERNAL_ACCESS_KEY_EXISTS + {AB42824F-D996-4DCA-89B1-A50D9EBE95A4} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.ssmssqlproj b/Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.ssmssqlproj deleted file mode 100644 index 87a7419d6..000000000 --- a/Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.ssmssqlproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - EnableExternalAccessTests.class.sql - - - - - - Private_InitTests_EAKE.class.sql - - - - - - - - \ No newline at end of file diff --git a/Tests.SA/Tests.SA.sqlproj b/Tests.SA/Tests.SA.sqlproj new file mode 100644 index 000000000..88aebb1a0 --- /dev/null +++ b/Tests.SA/Tests.SA.sqlproj @@ -0,0 +1,13 @@ + + + + + Tests.SA + {4183AC53-E498-4F50-9B76-2DDB36DBAA83} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Tests.SA/Tests.SA.ssmssqlproj b/Tests.SA/Tests.SA.ssmssqlproj deleted file mode 100644 index ac9b70c20..000000000 --- a/Tests.SA/Tests.SA.ssmssqlproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - _ExploratoryTests_SA.class.sql - - - - - - InstallAssemblyKeyTests.class.sql - - - - - - InstallExternalAccessKeyTests.class.sql - - - - - - PrepareServerTests.class.sql - - - - - - Private_EnableCLRTests.class.sql - - - - - - RemoveAssemblyKeyTests.class.sql - - - - - - RemoveExternalAccessKeyTests.class.sql - - - - - - - - \ No newline at end of file diff --git a/Tests/FriendlySQLServerVersionTests.class.sql b/Tests/FriendlySQLServerVersionTests.class.sql index f801c3242..70338db35 100644 --- a/Tests/FriendlySQLServerVersionTests.class.sql +++ b/Tests/FriendlySQLServerVersionTests.class.sql @@ -138,6 +138,17 @@ BEGIN EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; END; GO +--[@tSQLt:MaxSqlMajorVersion](16) +--[@tSQLt:MinSqlMajorVersion](16) +CREATE PROCEDURE FriendlySQLServerVersionTests.[test returns 2022 for the actual ProductVersion on 2022] +AS +BEGIN + DECLARE @CurrentProductVersion NVARCHAR(128) = CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)); + EXEC FriendlySQLServerVersionTests.AssertReturnsCorrectFriendlyVersion + @Productversion = @CurrentProductVersion, + @ExpectedVersion = '2022'; +END; +GO --[@tSQLt:MaxSqlMajorVersion](15) --[@tSQLt:MinSqlMajorVersion](15) CREATE PROCEDURE FriendlySQLServerVersionTests.[test returns 2019 for the actual ProductVersion on 2019] diff --git a/Tests/TableToTextTests.class.sql b/Tests/TableToTextTests.class.sql index 3ff98201e..a84aba4f5 100644 --- a/Tests/TableToTextTests.class.sql +++ b/Tests/TableToTextTests.class.sql @@ -24,7 +24,7 @@ BEGIN BEGIN TRY DECLARE @r NVARCHAR(MAX); - SET @r = tSQLt.Private::TableToString('DoesNotExist', '', NULL); + EXEC tSQLt.TableToText @r OUT, 'DoesNotExist', '', NULL; END TRY BEGIN CATCH SET @err = ERROR_MESSAGE(); @@ -40,21 +40,27 @@ GO CREATE PROCEDURE TableToTextTests.[test TableToText throws exception if tablename is NULL] AS BEGIN + EXEC tSQLt.ExpectException @ExpectedMessagePattern = '%@TableName cannot be NULL%' - DECLARE @err NVARCHAR(MAX); SET @err = 'No Exception occurred!'; + DECLARE @r NVARCHAR(MAX); + EXEC tSQLt.TableToText @r OUT, NULL, '', NULL; + + -- RETURN; + + -- DECLARE @err NVARCHAR(MAX); SET @err = 'No Exception occurred!'; - BEGIN TRY - DECLARE @r NVARCHAR(MAX); - SET @r = tSQLt.Private::TableToString(NULL, '', NULL); - END TRY - BEGIN CATCH - SET @err = ERROR_MESSAGE(); - END CATCH + -- BEGIN TRY + -- DECLARE @r NVARCHAR(MAX); + -- EXEC tSQLt.TableToText @r OUT, NULL, '', NULL; + -- END TRY + -- BEGIN CATCH + -- SET @err = ERROR_MESSAGE(); + -- END CATCH - IF @err NOT LIKE '%Object name cannot be NULL%' - BEGIN - EXEC tSQLt.Fail 'Unexpected error message was: ', @err; - END; + -- IF @err NOT LIKE '%Object name cannot be NULL%' + -- BEGIN + -- EXEC tSQLt.Fail 'Unexpected error message was: ', @err; + -- END; END; GO @@ -66,7 +72,7 @@ BEGIN FROM (SELECT 1) AS x(y); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('[dbo].[DoesExist]', '', NULL); + EXEC tSQLt.TableToText @result OUT, '[dbo].[DoesExist]', '', NULL; EXEC tSQLt.AssertEqualsString '|y| +-+ @@ -82,7 +88,7 @@ BEGIN FROM (SELECT 1) AS x(y); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '| | +-+ @@ -96,13 +102,13 @@ BEGIN DECLARE @result NVARCHAR(MAX); DECLARE @cmd NVARCHAR(MAX); SET @cmd =' - CREATE TABLE #DoesExist(['+CHAR(8)+''']]] VARCHAR(1));INSERT INTO #DoesExist VALUES(''''); - SET @result = tSQLt.Private::TableToString(''#DoesExist'', '''', NULL); + CREATE TABLE #DoesExist(['+CHAR(9)+''']]] VARCHAR(1));INSERT INTO #DoesExist VALUES(''''); + EXEC tSQLt.TableToText @result OUT, ''#DoesExist'', '''', NULL; '; EXEC sp_executesql @cmd,N'@result NVARCHAR(MAX) OUT',@result OUT; DECLARE @expected NVARCHAR(MAX); - SET @expected ='|'+CHAR(8)+''']| + SET @expected ='|'+CHAR(9)+''']| +---+ | |'; EXEC tSQLt.AssertEqualsString @expected, @result; @@ -116,7 +122,7 @@ BEGIN DECLARE @cmd NVARCHAR(MAX); SET @cmd =' CREATE TABLE #DoesExist([[a]]] VARCHAR(1));INSERT INTO #DoesExist VALUES(''''); - SET @result = tSQLt.Private::TableToString(''#DoesExist'', '''', NULL); + EXEC tSQLt.TableToText @result OUT, ''#DoesExist'', '''', NULL; '; EXEC sp_executesql @cmd,N'@result NVARCHAR(MAX) OUT',@result OUT; @@ -140,7 +146,7 @@ BEGIN SELECT (POWER(CAST(-2 AS BIGINT),63)) T; DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +--------------------+ @@ -158,7 +164,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('This is my text value'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +---------------------+ @@ -175,7 +181,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(N'This is my text value'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +---------------------+ @@ -191,7 +197,7 @@ BEGIN ); INSERT INTO #DoesExist (T)VALUES(1.712345612345610E+308); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +----------------------+ @@ -208,7 +214,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('12345678901234567890123456789.123456789'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +---------------------------------------+ @@ -229,7 +235,7 @@ BEGIN SELECT @rowid = T FROM #DoesExist; DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; DECLARE @expected NVARCHAR(MAX); SET @expected = '|T | @@ -267,7 +273,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('d7b868c6-c16e-443d-9af9-b23cf83bec0b'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +------------------------------------+ @@ -284,7 +290,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('d1d2'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +----------------------------------------+ @@ -301,7 +307,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('2001-10-13T12:34:56.787'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +-----------------------+ @@ -318,7 +324,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('2001-10-13T15:34:56.787'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +----------------+ @@ -335,7 +341,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(REPLICATE(CAST('*' AS VARCHAR(MAX)),8001)); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; DECLARE @expected NVARCHAR(MAX); SELECT @expected = '|T'+REPLICATE(' ',154)+'| @@ -355,7 +361,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(CAST(REPLICATE(CAST('*' AS VARCHAR(MAX)),8001) AS VARBINARY(MAX))); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; DECLARE @expected NVARCHAR(MAX); SELECT @expected = '|T'+REPLICATE(' ',154)+'| @@ -375,7 +381,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('hello'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; DECLARE @expected NVARCHAR(MAX); SELECT @expected = '|T | @@ -395,7 +401,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(0xfedcba9876543210); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +------------------+ @@ -412,7 +418,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(0x111213141516171819102122232425262728292031323334353637383930414243444546474849405152535455565758595061626364656667686960717273747576777879708182838485868788898091929394959697989990); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +-----------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -429,7 +435,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +-----------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -446,7 +452,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +-----------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -464,7 +470,7 @@ GO -- INSERT INTO #DoesExist (T12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345)VALUES('1234567890123456789012345678901234567890123456789012345'); -- DECLARE @result NVARCHAR(MAX); --- SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); +-- EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; -- EXEC tSQLt.AssertEqualsString '|T123456789012345678901234<...>1234567890123456789012345| --+-------------------------------------------------------+ @@ -480,7 +486,7 @@ BEGIN FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; IF (ISNULL(@result,'') NOT LIKE '|no| +--+ @@ -507,7 +513,7 @@ BEGIN FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', NULL, NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', NULL, NULL; IF (ISNULL(@result,'') NOT LIKE '|no| +--+ @@ -533,7 +539,7 @@ BEGIN FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist','10-no+10*(no%2)', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '10-no+10*(no%2)', NULL; EXEC tSQLt.AssertEqualsString '|no| +--+ @@ -552,7 +558,7 @@ BEGIN FROM tSQLt.F_Num(0); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|no| +--+', @result; @@ -567,7 +573,7 @@ BEGIN FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist','no', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', 'no', NULL; EXEC tSQLt.AssertEqualsString '|no|FromTen|NullCol| +--+-------+-------+ @@ -586,7 +592,8 @@ BEGIN FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist','no','[Col1],[Col2],[Col3]'); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', 'no', '[Col1],[Col2],[Col3]'; + EXEC tSQLt.TableToText @result OUT, '#DoesExist','no','[Col1],[Col2],[Col3]'; EXEC tSQLt.AssertEqualsString '|Col1|Col2|Col3 | +----+----+------+ @@ -605,7 +612,7 @@ BEGIN FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist','', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|n | +------+ @@ -634,8 +641,8 @@ PRINT @cols; FROM tSQLt.F_Num(4); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist','C001', NULL); - + EXEC tSQLt.TableToText @result OUT, '#DoesExist', 'C001', NULL; + EXEC tSQLt.AssertEqualsString '|C001|C002|C003|C004|C005|C006|C007|C008|C009|C010|C011|C012|C013|C014|C015|C016|C017|C018|C019|C020|C021|C022|C023|C024|C025|C026|C027|C028|C029|C030|C031|C032|C033|C034|C035|C036|C037|C038|C039|C040|C041|C042|C043|C044|C045|C046|C047|C048|C049|C050|C051|C052|C053|C054|C055|C056|C057|C058|C059|C060|C061|C062|C063|C064|C065|C066|C067|C068|C069|C070|C071|C072|C073|C074|C075|C076|C077|C078|C079|C080|C081|C082|C083|C084|C085|C086|C087|C088|C089|C090|C091|C092|C093|C094|C095|C096|C097|C098|C099|C100| +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |32 |33 |34 |35 |36 |37 |38 |39 |40 |41 |42 |43 |44 |45 |46 |47 |48 |49 |50 |51 |52 |53 |54 |55 |56 |57 |58 |59 |60 |61 |62 |63 |64 |65 |66 |67 |68 |69 |70 |71 |72 |73 |74 |75 |76 |77 |78 |79 |80 |81 |82 |83 |84 |85 |86 |87 |88 |89 |90 |91 |92 |93 |94 |95 |96 |97 |98 |99 |100 |101 | @@ -653,7 +660,7 @@ BEGIN FROM (SELECT 1,2) AS x(a,b); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('[dbo].[DoesExist]', '', '[a],[b]'); + EXEC tSQLt.TableToText @result OUT, '[dbo].[DoesExist]', '', '[a],[b]'; EXEC tSQLt.AssertEqualsString '|a|b| +-+-+ @@ -669,7 +676,7 @@ BEGIN FROM (SELECT 1,2) AS x([[a]]],[]]b[]); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('[dbo].[DoesExist]', '', '[[a]]],[]]b[]'); + EXEC tSQLt.TableToText @result OUT, '[dbo].[DoesExist]', '', '[[a]]],[]]b[]'; EXEC tSQLt.AssertEqualsString '|[a]|]b[| +---+---+ @@ -685,7 +692,7 @@ BEGIN FROM (SELECT 1,2) AS x(a,[b,c]); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('[dbo].[DoesExist]', '', NULL); + EXEC tSQLt.TableToText @result OUT, '[dbo].[DoesExist]', '', NULL; EXEC tSQLt.AssertEqualsString '|a|b,c| +-+---+ @@ -701,7 +708,7 @@ BEGIN FROM (SELECT 1,2) AS x(a,b); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('[dbo].[DoesExist]', '', '[a],[b,c]'); + EXEC tSQLt.TableToText @result OUT, '[dbo].[DoesExist]', '', '[a],[b,c]'; EXEC tSQLt.AssertEqualsString '|a|b,c| +-+---+ @@ -717,7 +724,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(CAST('2001-10-13 12:34:56.7891234 +13:24' AS DATETIMEOFFSET)); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +----------------------------------+ @@ -734,7 +741,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES(CAST('2001-10-13T12:34:56.7891234' AS DATETIME2)); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +---------------------------+ @@ -751,7 +758,7 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('2001-10-13T12:34:56.7871234'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +----------------+ @@ -768,10 +775,102 @@ BEGIN INSERT INTO #DoesExist (T)VALUES('2001-10-13T12:34:56.787'); DECLARE @result NVARCHAR(MAX); - SET @result = tSQLt.Private::TableToString('#DoesExist', '', NULL); + EXEC tSQLt.TableToText @result OUT, '#DoesExist', '', NULL; EXEC tSQLt.AssertEqualsString '|T | +----------+ |2001-10-13|', @result; END; GO + +CREATE PROCEDURE TableToTextTests.[test TableToText works for CLR datatype that is not in tempdb] +AS +BEGIN + IF(OBJECT_ID('TableToTextTests.DoesExist')IS NOT NULL)DROP TABLE TableToTextTests.DoesExist; + CREATE TABLE TableToTextTests.DoesExist( + T tSQLt_testutil.DataTypeByteOrdered + ); + INSERT INTO TableToTextTests.DoesExist (T)VALUES('42'); + + DECLARE @result NVARCHAR(MAX); + EXEC tSQLt.TableToText @result OUT, 'TableToTextTests.DoesExist', '', NULL; + + EXEC tSQLt.AssertEqualsString '|T | ++--------------------------+ +|<>|', @result; +END; +GO + +CREATE PROCEDURE TableToTextTests.[test TableToText does not add or remove objects] +AS +BEGIN + IF(OBJECT_ID('TableToTextTests.DoesExist')IS NOT NULL)DROP TABLE TableToTextTests.DoesExist; + CREATE TABLE TableToTextTests.DoesExist( + T INT + ); + + SELECT object_id,name INTO #PreState FROM sys.objects; + + DECLARE @result NVARCHAR(MAX); + EXEC tSQLt.TableToText @result OUT, 'TableToTextTests.DoesExist', '', NULL; + + SELECT + CASE WHEN O.object_id IS NULL THEN 'DELETED' ELSE 'ADDED' END [action], + CASE WHEN O.object_id IS NULL THEN P.object_id ELSE O.object_id END object_id, + CASE WHEN O.object_id IS NULL THEN P.name ELSE O.name END [name] + INTO #Actual + FROM sys.objects O + FULL JOIN #PreState P + ON O.name = P.name + AND O.object_id = P.object_id + WHERE O.object_id IS NULL + OR P.object_id IS NULL; + EXEC tSQLt.AssertEmptyTable @TableName = '#Actual'; +END; +GO +CREATE PROCEDURE TableToTextTests.[test TableToText tags temporary object] +AS +BEGIN + IF(OBJECT_ID('TableToTextTests.DoesExist')IS NOT NULL)DROP TABLE TableToTextTests.DoesExist; + CREATE TABLE TableToTextTests.DoesExist( + T INT + ); + + DECLARE @cmd NVARCHAR(MAX) = + 'ALTER PROCEDURE tSQLt.Private_MarktSQLtTempObject '+ + '@ObjectName NVARCHAR(MAX),@ObjectType NVARCHAR(MAX),@NewNameOfOriginalObject NVARCHAR(4000) = NULL '+ + 'AS BEGIN '+ + ' INSERT INTO [#TableToTextTests.PostState] SELECT object_id,name FROM sys.objects;'+ + ' INSERT INTO [#TableToTextTests.Parameters] SELECT OBJECT_ID(@ObjectName),@ObjectType;'+ + 'END;'; + EXEC(@cmd); + + SELECT TOP(0) CAST('' AS INT) ObjectId,CAST('' AS NVARCHAR(MAX)) ObjectType + INTO [#TableToTextTests.Parameters]; + SELECT object_id,name INTO [#TableToTextTests.PreState] FROM sys.objects; + SELECT TOP(0) object_id,name INTO [#TableToTextTests.PostState] FROM sys.objects; + + DECLARE @result NVARCHAR(MAX); + EXEC tSQLt.TableToText @result OUT, 'TableToTextTests.DoesExist', '', NULL; + + SELECT * + INTO #Actual + FROM + ( + SELECT PO.* + FROM [#TableToTextTests.PostState] PO + LEFT JOIN [#TableToTextTests.PreState] PR + ON PO.name = PR.name + AND PO.object_id = PR.object_id + WHERE PR.object_id IS NULL + ) PO + FULL JOIN [#TableToTextTests.Parameters] PA + ON PO.object_id = PA.ObjectId + AND PA.ObjectType = 'TABLE' + WHERE PO.object_id IS NULL + OR PA.ObjectId IS NULL; + + EXEC tSQLt.AssertEmptyTable '#Actual'; + +END; +GO diff --git a/Tests/Tests.sqlproj b/Tests/Tests.sqlproj new file mode 100644 index 000000000..49f3673f2 --- /dev/null +++ b/Tests/Tests.sqlproj @@ -0,0 +1,13 @@ + + + + + Tests + {5A1279BA-7094-4A0B-87E9-A1B3637B4F3D} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + 1033, CI + + + + + \ No newline at end of file diff --git a/Tests/Tests.ssmssqlproj b/Tests/Tests.ssmssqlproj deleted file mode 100644 index a8a5e1d36..000000000 --- a/Tests/Tests.ssmssqlproj +++ /dev/null @@ -1,435 +0,0 @@ - - - - - - - - - - - - - _ExploratoryTests.class.sql - - - - - - AnnotationHostPlatformTests.class.sql - - - - - - AnnotationNoTransactionTests.class.sql - - - - - - AnnotationSkipTestTests.class.sql - - - - - - AnnotationSqlServerVersionTests.class.sql - - - - - - AnnotationsTests.class.sql - - - - - - ApplyConstraintTests.class.sql - - - - - - ApplyTriggerTests.class.sql - - - - - - AssertEmptyTableTests.class.sql - - - - - - AssertEqualsStringTests.class.sql - - - - - - AssertEqualsTableSchemaTests.class.sql - - - - - - AssertEqualsTableTests.class.sql - - - - - - AssertEqualsTests.class.sql - - - - - - AssertLikeTests.class.sql - - - - - - AssertNotEqualsTests.class.sql - - - - - - AssertObjectDoesNotExistTests.class.sql - - - - - - AssertObjectExistsTests.class.sql - - - - - - AssertResultSetsHaveSameMetaDataTests.class.sql - - - - - - AssertStringInTests.class.sql - - - - - - BootStrapTest.sql - - - - - - DropClassTests.class.sql - - - - - - ExpectExceptionTests.class.sql - - - - - - ExpectNoExceptionTests.class.sql - - - - - - FailTests.class.sql - - - - - - FakeFunctionTests.class.sql - - - - - - FakeTableTests.class.sql - - - - - - FriendlySQLServerVersionTests.class.sql - - - - - - InfoTests.class.sql - - - - - - NameAndIdResolution_test.class.sql - - - - - - NewTestClassTests.class.sql - - - - - - Private_AssertNoSideEffectsTests.class.sql - - - - - - Private_CleanUpCmdHandlerTests.class.sql - - - - - - Private_CleanUpTests.class.sql - - - - - - Private_CreateFakeFunctionStatementTests.class.sql - - - - - - Private_GetAnnotationListTests.class.sql - - - - - - Private_GetFormattedErrorInfoTests.class.sql - - - - - - Private_GetFullTypeNameTests.class.sql - - - - - - Private_GetSQLProductMajorVersionTests.class.sql - - - - - - Private_HandleMessageAndResultTests.class.sql - - - - - - Private_InitTests.class.sql - - - - - - Private_InstallationInfoTests.class.sql - - - - - - Private_MarktSQLtTempObjectTests.class.sql - - - - - - Private_NoTransactionHandleTableTests.class.sql - - - - - - Private_NoTransactionTableActionTests.class.sql - - - - - - Private_NoTransactionHandleTablesTests.class.sql - - - - - - Private_ProcessTestAnnotationsTests.class.sql - - - - - - Private_RemoveSchemaBindingTests.class.sql - - - - - - Private_RemoveSchemaBoundReferencesTests.class.sql - - - - - - Private_RenameObjectToUniqueNameTests.class.sql - - - - - - Private_ResetNewTestClassListTests.class.sql - - - - - - Private_ResultsTests.class.sql - - - - - - Private_ScriptIndexTests.class.sql - - - - - - Private_SeizeTests.class.sql - - - - - - Private_SplitSqlVersionTests.class.sql - - - - - - Private_SqlVariantFormatterTests.class.sql - - - - - - RemoveObjectIfExistsTests.class.sql - - - - - - RemoveObjectTests.class.sql - - - - - - RenameClassTests.class.sql - - - - - - ResetTests.class.sql - - - - - - ResultSetFilterTests.class.sql - - - - - - Run_Methods_Tests.class.sql - - - - - - SetSummaryErrorTests.class.sql - - - - - - SpyProcedureTests.class.sql - - - - - - StubRecordTests.class.sql - - - - - - TableToTextTests.class.sql - - - - - - TestClassesTest.class.sql - - - - - - tSQLt_test.class.sql - - - - - - tSQLtclr_test.class.sql - - - - - - UndoTestDoublesTests.class.sql - - - - - - UninstallTests.class.sql - - - - - - - - \ No newline at end of file diff --git a/tSQLt b/tSQLt deleted file mode 160000 index 8a3639d8c..000000000 --- a/tSQLt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8a3639d8cc53ca5560a49c9a6baa4a5ff7dbb39a diff --git a/tSQLt.code-workspace b/tSQLt.code-workspace index 07f82761d..fd39ede6f 100644 --- a/tSQLt.code-workspace +++ b/tSQLt.code-workspace @@ -6,6 +6,9 @@ ], "settings": { "powershell.codeFormatting.addWhitespaceAroundPipe": true, - "yaml.schemaStore.enable": false +"yaml.schemaStore.enable": false, +"dataworkspace.excludedProjects": [ +], +"dotnet.preferCSharpExtension": true } } \ No newline at end of file diff --git a/tSQLtCLR/Build.ps1 b/tSQLtCLR/Build.ps1 new file mode 100644 index 000000000..a0ff38bfc --- /dev/null +++ b/tSQLtCLR/Build.ps1 @@ -0,0 +1,35 @@ +param( + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $pfxFilePath , + [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][securestring] $pfxPassword +) +Push-Location -Path $PSScriptRoot + +# Create a unique temporary directory for this process +$randomNumber = Get-Random -Minimum 10000 -Maximum 99999 +$tempDir = Join-Path -Path "/tmp" -ChildPath $("myapp_${PID}_$randomNumber") +try{ + New-Item -Path $tempDir -ItemType Directory -Force + Invoke-Expression "chmod 700 '$tempDir'" + + $snkFilePath = Join-Path -Path $tempDir -ChildPath "tSQLtOfficialSigningKey.snk" + $pemFilePath = Join-Path -Path $tempDir -ChildPath "tSQLtOfficialSigningKey.pem" + + + # $pfxPasswordCleartext = (ConvertFrom-SecureString $pfxPassword -AsPlainText); + $pfxPasswordCleartext = [System.Runtime.InteropServices.Marshal]::PtrToStringUni([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pfxPassword)); + & openssl pkcs12 -in "$pfxFilePath" -out "$pemFilePath" -nodes -passin pass:$pfxPasswordCleartext + & openssl pkcs12 -in "$pfxFilePath" -noout -info -nodes -passin pass:$pfxPasswordCleartext + Write-Warning("Certificate Thumbprint: " + (Get-PfxCertificate -Filepath "$pfxFilePath" -Password $pfxPassword).Thumbprint.ToString()); + + $rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider + $pemContent = Get-Content -Path "$pemFilePath" -Raw + $rsa.ImportFromPem($pemContent.ToCharArray()) + $keyPair = $rsa.ExportCspBlob($true) + [System.IO.File]::WriteAllBytes($snkFilePath, $keyPair) + + & dotnet build /p:tSQLtOfficialSigningKey="$snkFilePath" +} +finally { + try{Remove-Item -Path $tempDir -Recurse -Force}catch{Write-Host "deleting tempdir failed!"} + Pop-Location +} \ No newline at end of file diff --git a/tSQLtCLR/FxCopProject.FxCop b/tSQLtCLR/FxCopProject.FxCop deleted file mode 100644 index a54ec68c7..000000000 --- a/tSQLtCLR/FxCopProject.FxCop +++ /dev/null @@ -1,190 +0,0 @@ - - - - True - c:\programs\microsoft fxcop 1.36\Xml\FxCopReport.xsl - - - - - - True - True - True - 10 - 1 - - False - - False - 120 - False - - - - - - - - - - - - - - - - - - - - - - - - - - tSQLtCLR - - - - - - - - - - CLR - tSQLtCLR - Clr - - - - - - - - - - Lt - tSQLtCLR - LT - - - - - - - - - - t - tSQLtCLR - T - - - - - - - - - - - - - - - - - - CLR - 'tSQLtCLR.dll' - Clr - - - - - - - - - - Lt - 'tSQLtCLR.dll' - LT - - - - - - - - - - t - 'tSQLtCLR.dll' - T - - - - - - - - - - - - - - - - - - MetaData - 'StoredProcedures.AssertResultSetsHaveSameMetaData(SqlString, SqlString)' - Metadata - - - - - - - - - - - - - - - - - - - - - tSQLt is the product name - tSQLt is the product name - tSQLt is the product name - tSQLtCLR is likely to contain many more types in the future - tSQLt is the product name - tSQLt is the product name - MetaData (with capital D is the .Net convention for the term) - - - - - Consider merging the types defined in '{0}' with another namespace. - - - The compound word '{0}' in member name {1} exists as a discrete term. If your usage is intended to be single word, case it as '{2}' or strip the first token entirely if it represents any sort of Hungarian notation. - - - Correct the casing of '{0}' in assembly name {1} by changing it to '{2}'. - Correct the casing of '{0}' in namespace name '{1}' by changing it to '{2}'. - - - - diff --git a/tSQLtCLR/UnsignedEmpty/Properties/AssemblyInfo.cs b/tSQLtCLR/UnsignedEmpty/Properties/XXXX.AssemblyInfo.cs.XXXX similarity index 100% rename from tSQLtCLR/UnsignedEmpty/Properties/AssemblyInfo.cs rename to tSQLtCLR/UnsignedEmpty/Properties/XXXX.AssemblyInfo.cs.XXXX diff --git a/tSQLtCLR/UnsignedEmpty/UnsignedEmpty.csproj b/tSQLtCLR/UnsignedEmpty/UnsignedEmpty.csproj index 0c9bd76b8..1c174ec89 100644 --- a/tSQLtCLR/UnsignedEmpty/UnsignedEmpty.csproj +++ b/tSQLtCLR/UnsignedEmpty/UnsignedEmpty.csproj @@ -1,55 +1,25 @@ - - - - - Debug - AnyCPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8} - Library - Properties - UnsignedEmpty - UnsignedEmpty - v3.5 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\CruiseControl\ - - - bin\CI%28NoSigning%29\ - AnyCPU - MinimumRecommendedRules.ruleset - - - bin\NoSigningForCI\ - - - - - - - \ No newline at end of file + + + net40 + true + UnsignedEmpty + An empty (no code) assembly that is not signed + tSQLt Foundation + tSQLt + Copyright © sqlity.net 2010 - $(Year) + false + true + Release + + false + false + true + + + + $([System.DateTime]::Now.Year) + 1.0.0.0 + $(AssemblyVersion) + + + diff --git a/tSQLtCLR/UnsignedEmpty/XXXX.UnsignedEmpty.csproj.XXXX b/tSQLtCLR/UnsignedEmpty/XXXX.UnsignedEmpty.csproj.XXXX new file mode 100644 index 000000000..0c9bd76b8 --- /dev/null +++ b/tSQLtCLR/UnsignedEmpty/XXXX.UnsignedEmpty.csproj.XXXX @@ -0,0 +1,55 @@ + + + + + Debug + AnyCPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8} + Library + Properties + UnsignedEmpty + UnsignedEmpty + v3.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + bin\CruiseControl\ + + + bin\CI%28NoSigning%29\ + AnyCPU + MinimumRecommendedRules.ruleset + + + bin\NoSigningForCI\ + + + + + + + \ No newline at end of file diff --git a/tSQLtCLR/XXXX.tSQLtCLR.sln.XXXX b/tSQLtCLR/XXXX.tSQLtCLR.sln.XXXX new file mode 100644 index 000000000..2b64de9fc --- /dev/null +++ b/tSQLtCLR/XXXX.tSQLtCLR.sln.XXXX @@ -0,0 +1,124 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29509.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtCLR", "tSQLtCLR\tSQLtCLR.csproj", "{309A14D6-7C8A-4022-BC2C-409FD7FE48AB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtTestUtilCLR", "tSQLtTestUtilCLR\tSQLtTestUtilCLR.csproj", "{87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtAssemblyKey", "tSQLtAssemblyKey\tSQLtAssemblyKey.csproj", "{09611E35-7E79-4DD3-8BCD-83F27535FB5D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnsignedEmpty", "UnsignedEmpty\UnsignedEmpty.csproj", "{14624277-A18F-4D80-BC04-FDFCD09E13D8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + CruiseControl|Any CPU = CruiseControl|Any CPU + CruiseControl|Mixed Platforms = CruiseControl|Mixed Platforms + CruiseControl|x86 = CruiseControl|x86 + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + NoSigningForCI|Any CPU = NoSigningForCI|Any CPU + NoSigningForCI|Mixed Platforms = NoSigningForCI|Mixed Platforms + NoSigningForCI|x86 = NoSigningForCI|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Mixed Platforms.ActiveCfg = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Mixed Platforms.Build.0 = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|x86.ActiveCfg = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Any CPU.ActiveCfg = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Any CPU.Build.0 = CruiseControl|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Any CPU.Build.0 = Release|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|x86.ActiveCfg = Release|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Mixed Platforms.ActiveCfg = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Mixed Platforms.Build.0 = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|x86.ActiveCfg = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Any CPU.ActiveCfg = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Any CPU.Build.0 = CruiseControl|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|x86.ActiveCfg = Debug|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Any CPU.Build.0 = Release|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|x86.ActiveCfg = Release|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Mixed Platforms.ActiveCfg = CruiseControl|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Mixed Platforms.Build.0 = CruiseControl|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|x86.ActiveCfg = CruiseControl|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|x86.Build.0 = CruiseControl|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|x86.ActiveCfg = Debug|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|x86.Build.0 = Debug|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Any CPU.Build.0 = Release|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|x86.ActiveCfg = Release|Any CPU + {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|x86.Build.0 = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Mixed Platforms.ActiveCfg = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Mixed Platforms.Build.0 = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|x86.ActiveCfg = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|x86.ActiveCfg = Debug|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Any CPU.Build.0 = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {732D09E1-56A0-4FFC-A5EC-6EBCEE3F7E92} + EndGlobalSection +EndGlobal diff --git a/tSQLtCLR/tSQLtAssemblyKey/Properties/AssemblyInfo.cs b/tSQLtCLR/tSQLtAssemblyKey/Properties/XXXX.AssemblyInfo.cs.XXXX similarity index 100% rename from tSQLtCLR/tSQLtAssemblyKey/Properties/AssemblyInfo.cs rename to tSQLtCLR/tSQLtAssemblyKey/Properties/XXXX.AssemblyInfo.cs.XXXX diff --git a/tSQLtCLR/tSQLtAssemblyKey/XXXX.tSQLtAssemblyKey.csproj.XXXX b/tSQLtCLR/tSQLtAssemblyKey/XXXX.tSQLtAssemblyKey.csproj.XXXX new file mode 100644 index 000000000..6ffe68631 --- /dev/null +++ b/tSQLtCLR/tSQLtAssemblyKey/XXXX.tSQLtAssemblyKey.csproj.XXXX @@ -0,0 +1,110 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {09611E35-7E79-4DD3-8BCD-83F27535FB5D} + Library + Properties + tSQLtAssemblyKey + tSQLtAssemblyKey + v2.0 + + + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + bin\CruiseControl\ + TRACE + true + pdbonly + AnyCPU + prompt + + + bin\NoSigningForCI\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + + + + False + Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/tSQLtCLR/tSQLtAssemblyKey/tSQLtAssemblyKey.csproj b/tSQLtCLR/tSQLtAssemblyKey/tSQLtAssemblyKey.csproj index 6ffe68631..ea7c7ac13 100644 --- a/tSQLtCLR/tSQLtAssemblyKey/tSQLtAssemblyKey.csproj +++ b/tSQLtCLR/tSQLtAssemblyKey/tSQLtAssemblyKey.csproj @@ -1,110 +1,48 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {09611E35-7E79-4DD3-8BCD-83F27535FB5D} - Library - Properties - tSQLtAssemblyKey - tSQLtAssemblyKey - v2.0 - - - 512 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\CruiseControl\ - TRACE - true - pdbonly - AnyCPU - prompt - - - bin\NoSigningForCI\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - - - - False - Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - - - + + + + 1 + 1 + + - - + net40 + true + tSQLtAssemblyKey + The CLR for installing the SigningKey of the tSQLt unit testing framework + tSQLt Foundation + tSQLt + Copyright © sqlity.net 2010 - $(Year) + false + true + Release + + true + $(tSQLtOfficialSigningKey) + false + true - + + - --> - \ No newline at end of file + + + + diff --git a/tSQLtCLR/tSQLtCLR.sln b/tSQLtCLR/tSQLtCLR.sln index 2b64de9fc..158e0afa5 100644 --- a/tSQLtCLR/tSQLtCLR.sln +++ b/tSQLtCLR/tSQLtCLR.sln @@ -1,124 +1,40 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29509.3 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtCLR", "tSQLtCLR\tSQLtCLR.csproj", "{309A14D6-7C8A-4022-BC2C-409FD7FE48AB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtAssemblyKey", "tSQLtAssemblyKey\tSQLtAssemblyKey.csproj", "{C4788CD5-0135-4673-9DAC-A5B12A67FC2F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtTestUtilCLR", "tSQLtTestUtilCLR\tSQLtTestUtilCLR.csproj", "{87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtCLR", "tSQLtCLR\tSQLtCLR.csproj", "{14F77242-1DE1-4793-BDD6-60A745782D49}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtAssemblyKey", "tSQLtAssemblyKey\tSQLtAssemblyKey.csproj", "{09611E35-7E79-4DD3-8BCD-83F27535FB5D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tSQLtTestUtilCLR", "tSQLtTestUtilCLR\tSQLtTestUtilCLR.csproj", "{293236E9-8A9F-4966-AD56-CFE395009DE7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnsignedEmpty", "UnsignedEmpty\UnsignedEmpty.csproj", "{14624277-A18F-4D80-BC04-FDFCD09E13D8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnsignedEmpty", "UnsignedEmpty\UnsignedEmpty.csproj", "{83863674-4DC7-4FB5-8E56-DDD48D350A91}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - CruiseControl|Any CPU = CruiseControl|Any CPU - CruiseControl|Mixed Platforms = CruiseControl|Mixed Platforms - CruiseControl|x86 = CruiseControl|x86 Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x86 = Debug|x86 - NoSigningForCI|Any CPU = NoSigningForCI|Any CPU - NoSigningForCI|Mixed Platforms = NoSigningForCI|Mixed Platforms - NoSigningForCI|x86 = NoSigningForCI|x86 Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Mixed Platforms.ActiveCfg = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|Mixed Platforms.Build.0 = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.CruiseControl|x86.ActiveCfg = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Any CPU.ActiveCfg = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Any CPU.Build.0 = CruiseControl|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Debug|x86.ActiveCfg = Debug|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Any CPU.Build.0 = Release|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB}.Release|x86.ActiveCfg = Release|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Mixed Platforms.ActiveCfg = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|Mixed Platforms.Build.0 = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.CruiseControl|x86.ActiveCfg = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Any CPU.ActiveCfg = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Any CPU.Build.0 = CruiseControl|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Debug|x86.ActiveCfg = Debug|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Any CPU.ActiveCfg = Release|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Any CPU.Build.0 = Release|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89}.Release|x86.ActiveCfg = Release|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Mixed Platforms.ActiveCfg = CruiseControl|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|Mixed Platforms.Build.0 = CruiseControl|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|x86.ActiveCfg = CruiseControl|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.CruiseControl|x86.Build.0 = CruiseControl|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|x86.ActiveCfg = Debug|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Debug|x86.Build.0 = Debug|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Any CPU.Build.0 = Release|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|x86.ActiveCfg = Release|Any CPU - {09611E35-7E79-4DD3-8BCD-83F27535FB5D}.Release|x86.Build.0 = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Any CPU.ActiveCfg = CruiseControl|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Any CPU.Build.0 = CruiseControl|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Mixed Platforms.ActiveCfg = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|Mixed Platforms.Build.0 = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.CruiseControl|x86.ActiveCfg = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Debug|x86.ActiveCfg = Debug|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Any CPU.ActiveCfg = NoSigningForCI|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Any CPU.Build.0 = NoSigningForCI|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Mixed Platforms.ActiveCfg = NoSigningForCI|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|Mixed Platforms.Build.0 = NoSigningForCI|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|x86.ActiveCfg = NoSigningForCI|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.NoSigningForCI|x86.Build.0 = NoSigningForCI|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Any CPU.Build.0 = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {14624277-A18F-4D80-BC04-FDFCD09E13D8}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {732D09E1-56A0-4FFC-A5EC-6EBCEE3F7E92} + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C4788CD5-0135-4673-9DAC-A5B12A67FC2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4788CD5-0135-4673-9DAC-A5B12A67FC2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4788CD5-0135-4673-9DAC-A5B12A67FC2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4788CD5-0135-4673-9DAC-A5B12A67FC2F}.Release|Any CPU.Build.0 = Release|Any CPU + {14F77242-1DE1-4793-BDD6-60A745782D49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14F77242-1DE1-4793-BDD6-60A745782D49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14F77242-1DE1-4793-BDD6-60A745782D49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14F77242-1DE1-4793-BDD6-60A745782D49}.Release|Any CPU.Build.0 = Release|Any CPU + {293236E9-8A9F-4966-AD56-CFE395009DE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {293236E9-8A9F-4966-AD56-CFE395009DE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {293236E9-8A9F-4966-AD56-CFE395009DE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {293236E9-8A9F-4966-AD56-CFE395009DE7}.Release|Any CPU.Build.0 = Release|Any CPU + {83863674-4DC7-4FB5-8E56-DDD48D350A91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83863674-4DC7-4FB5-8E56-DDD48D350A91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83863674-4DC7-4FB5-8E56-DDD48D350A91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83863674-4DC7-4FB5-8E56-DDD48D350A91}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/tSQLtCLR/tSQLtCLR/AssemblyCopyright.cs b/tSQLtCLR/tSQLtCLR/AssemblyCopyright.cs deleted file mode 100644 index 8bb5c6259..000000000 --- a/tSQLtCLR/tSQLtCLR/AssemblyCopyright.cs +++ /dev/null @@ -1,4 +0,0 @@ -using System; -using System.Reflection; - -[assembly: AssemblyCopyright("Copyright © sqlity.net 2010 - 2015")] \ No newline at end of file diff --git a/tSQLtCLR/tSQLtCLR/AssemblyCopyright.tt b/tSQLtCLR/tSQLtCLR/AssemblyCopyright.tt deleted file mode 100644 index 5de0ed9e8..000000000 --- a/tSQLtCLR/tSQLtCLR/AssemblyCopyright.tt +++ /dev/null @@ -1,5 +0,0 @@ -<#@ template language="C#" #> -using System; -using System.Reflection; - -[assembly: AssemblyCopyright("Copyright © sqlity.net 2010 - <#=DateTime.Now.Year#>")] \ No newline at end of file diff --git a/tSQLtCLR/tSQLtCLR/AssemblyInfo.cs b/tSQLtCLR/tSQLtCLR/AssemblyInfo.cs deleted file mode 100644 index b75bb2e6b..000000000 --- a/tSQLtCLR/tSQLtCLR/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Data.Sql; -using System; - - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("tSQLtCLR")] -[assembly: AssemblyDescription("CLRs for the tSQLt unit testing framework")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("sqlity.net")] -[assembly: AssemblyProduct("tSQLt")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] -[assembly: CLSCompliant(true)] - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.*")] - -// Sign assembly with key in this container: -[assembly: System.Reflection.AssemblyKeyNameAttribute("tSQLt_OfficialSigningKey")] diff --git a/tSQLtCLR/tSQLtCLR/XXXXX.XXXX b/tSQLtCLR/tSQLtCLR/XXXXX.XXXX new file mode 100644 index 000000000..9f299389b --- /dev/null +++ b/tSQLtCLR/tSQLtCLR/XXXXX.XXXX @@ -0,0 +1,136 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {309A14D6-7C8A-4022-BC2C-409FD7FE48AB} + Library + Properties + tSQLtCLR + v4.0 + tSQLtCLR + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + bin\CruiseControl\ + TRACE + true + pdbonly + AnyCPU + prompt + + + bin\NoSigningForCI\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + True + True + AssemblyCopyright.tt + + + + + + + + + + + + + + + TextTemplatingFileGenerator + AssemblyCopyright.cs + + + + false + + + false + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + IF ($(ConfigurationName))==(Release) "$(SolutionDir)tSQLtCLR\PostBuild.bat" "$(SolutionDir)" "$(TargetPath)" + + \ No newline at end of file diff --git a/tSQLtCLR/tSQLtCLR/tSQLtCLR.csproj.user b/tSQLtCLR/tSQLtCLR/XXXXX.user.XXXX similarity index 100% rename from tSQLtCLR/tSQLtCLR/tSQLtCLR.csproj.user rename to tSQLtCLR/tSQLtCLR/XXXXX.user.XXXX diff --git a/tSQLtCLR/tSQLtCLR/tSQLtCLR.csproj b/tSQLtCLR/tSQLtCLR/tSQLtCLR.csproj index 5f3139098..ebce6ab0c 100644 --- a/tSQLtCLR/tSQLtCLR/tSQLtCLR.csproj +++ b/tSQLtCLR/tSQLtCLR/tSQLtCLR.csproj @@ -1,136 +1,48 @@ - - + + + + 1 + 1 + + - Debug - AnyCPU - 9.0.30729 - 2.0 - {309A14D6-7C8A-4022-BC2C-409FD7FE48AB} - Library - Properties - tSQLtCLR - v2.0 - tSQLtCLR - - - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\CruiseControl\ - TRACE - true - pdbonly - AnyCPU - prompt - - - bin\NoSigningForCI\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset + net40 + true + tSQLtCLR + The CLR for the tSQLt unit testing framework + tSQLt Foundation + tSQLt + Copyright © sqlity.net 2010 - $(Year) + false + true + Release + + true + $(tSQLtOfficialSigningKey) + false + true + + + $([System.DateTime]::Now.Year) + + + + + 2000-01-01T00:00:00Z + $([System.DateTime]::Parse($(BaseDate)).Ticks) + $([System.DateTime]::UtcNow.Ticks) + $([MSBuild]::Subtract($(NowTicks), $(BaseDateTicks))) + $([System.TimeSpan]::FromTicks($(DiffTicks)).Days) + $([System.DateTime]::Now.TimeOfDay.TotalSeconds) + $([System.Convert]::ToInt32($([MSBuild]::Divide($(CurrentTimeInSeconds), 2)))) + $(BaseVersionMajor).$(BaseVersionMinor).$(DaysSince2000).$(HalfSecondsSinceMidnight) + $(AssemblyVersion) + + + + - - - - - - - - True - True - AssemblyCopyright.tt - - - - - - - - - - - - - - - TextTemplatingFileGenerator - AssemblyCopyright.cs - - - - false - - - false - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - - - IF ($(ConfigurationName))==(Release) "$(SolutionDir)tSQLtCLR\PostBuild.bat" "$(SolutionDir)" "$(TargetPath)" - - \ No newline at end of file + diff --git a/tSQLtCLR/tSQLtTestUtilCLR/DataTypeByteOrdered.cs b/tSQLtCLR/tSQLtTestUtilCLR/DataTypeByteOrdered.cs index 0f6a1a458..6e06ebf03 100644 --- a/tSQLtCLR/tSQLtTestUtilCLR/DataTypeByteOrdered.cs +++ b/tSQLtCLR/tSQLtTestUtilCLR/DataTypeByteOrdered.cs @@ -14,7 +14,7 @@ public class DataTypeByteOrdered : INullable, IBinarySerialize, IComparable public override string ToString() { - return "<>"; + return $"<>"; } public int CompareTo(object obj) diff --git a/tSQLtCLR/tSQLtTestUtilCLR/Properties/Settings.Designer.cs b/tSQLtCLR/tSQLtTestUtilCLR/Properties/Settings.Designer.cs deleted file mode 100644 index 51ce7315d..000000000 --- a/tSQLtCLR/tSQLtTestUtilCLR/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace tSQLtTestUtilCLR.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/tSQLtCLR/tSQLtTestUtilCLR/Properties/Settings.settings b/tSQLtCLR/tSQLtTestUtilCLR/Properties/Settings.settings deleted file mode 100644 index 049245f40..000000000 --- a/tSQLtCLR/tSQLtTestUtilCLR/Properties/Settings.settings +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/tSQLtCLR/tSQLtTestUtilCLR/Properties/AssemblyInfo.cs b/tSQLtCLR/tSQLtTestUtilCLR/Properties/XXX.AssemblyInfo.cs.XXXX similarity index 100% rename from tSQLtCLR/tSQLtTestUtilCLR/Properties/AssemblyInfo.cs rename to tSQLtCLR/tSQLtTestUtilCLR/Properties/XXX.AssemblyInfo.cs.XXXX diff --git a/tSQLtCLR/tSQLtTestUtilCLR/app.config b/tSQLtCLR/tSQLtTestUtilCLR/XXXX.app.config.XXXX similarity index 100% rename from tSQLtCLR/tSQLtTestUtilCLR/app.config rename to tSQLtCLR/tSQLtTestUtilCLR/XXXX.app.config.XXXX diff --git a/tSQLtCLR/tSQLtTestUtilCLR/XXXX.tSQLtTestUtilCLR.csproj.XXXX b/tSQLtCLR/tSQLtTestUtilCLR/XXXX.tSQLtTestUtilCLR.csproj.XXXX new file mode 100644 index 000000000..977061726 --- /dev/null +++ b/tSQLtCLR/tSQLtTestUtilCLR/XXXX.tSQLtTestUtilCLR.csproj.XXXX @@ -0,0 +1,85 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89} + Library + Properties + tSQLtTestUtilCLR + tSQLtTestUtilCLR + v2.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + bin\CruiseControl\ + TRACE + true + pdbonly + AnyCPU + prompt + + + bin\NoSigningForCI\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + True + True + Settings.settings + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + \ No newline at end of file diff --git a/tSQLtCLR/tSQLtTestUtilCLR/tSQLtTestUtilCLR.csproj b/tSQLtCLR/tSQLtTestUtilCLR/tSQLtTestUtilCLR.csproj index 977061726..4adcf45bb 100644 --- a/tSQLtCLR/tSQLtTestUtilCLR/tSQLtTestUtilCLR.csproj +++ b/tSQLtCLR/tSQLtTestUtilCLR/tSQLtTestUtilCLR.csproj @@ -1,85 +1,46 @@ - - + + + + 1 + 1 + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {87E64BC4-089C-4E9F-BCB2-DB12BDB5FB89} - Library - Properties - tSQLtTestUtilCLR - tSQLtTestUtilCLR - v2.0 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\CruiseControl\ - TRACE - true - pdbonly - AnyCPU - prompt + net40 + true + tSQLtTestUtilCLR + The CLR used for testing the tSQLt unit testing framework + tSQLt Foundation + tSQLt + Copyright © sqlity.net 2010 - $(Year) + false + true + Release + + true + $(tSQLtOfficialSigningKey) + false + true - - bin\NoSigningForCI\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - - - - - - - - - - - - True - True - Settings.settings - - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - \ No newline at end of file + + + +