tests/DBOpsFile.class.Tests.ps1
Param ( [switch]$Batch ) if ($PSScriptRoot) { $commandName = $MyInvocation.MyCommand.Name.Replace(".Tests.ps1", ""); $here = $PSScriptRoot } else { $commandName = "_ManualExecution"; $here = (Get-Item . ).FullName } if (!$Batch) { # Is not a part of the global batch => import module #Explicitly import the module for testing Import-Module "$here\..\dbops.psd1" -Force; Get-DBOModuleFileList -Type internal | ForEach-Object { . $_.FullName } } else { # Is a part of a batch, output some eye-catching happiness Write-Host "Running $commandName tests" -ForegroundColor Cyan } Add-Type -AssemblyName System.IO.Compression Add-Type -AssemblyName System.IO.Compression.FileSystem . "$here\..\internal\classes\DBOpsHelper.class.ps1" . "$here\..\internal\classes\DBOps.class.ps1" $packageName = Join-PSFPath -Normalize "$here\etc\$commandName.zip" $script1 = Join-PSFPath -Normalize "$here\etc\sqlserver-tests\success\1.sql" $script2 = Join-PSFPath -Normalize "$here\etc\sqlserver-tests\success\2.sql" $script3 = Join-PSFPath -Normalize "$here\etc\sqlserver-tests\success\3.sql" $fileObject1 = Get-Item $script1 $fileObject2 = Get-Item $script2 $fileObject3 = Get-Item $script3 Describe "DBOpsFile class tests" -Tag $commandName, UnitTests, DBOpsFile { BeforeAll { if (Test-Path $packageName) { Remove-Item $packageName } } AfterAll { if (Test-Path $packageName) { Remove-Item $packageName } } Context "tests DBOpsFile object creation" { AfterAll { if (Test-Path $packageName) { Remove-Item $packageName } } It "Should create new DBOpsFile object" { $f = [DBOpsFile]::new('1.sql') # $f | Should -Not -BeNullOrEmpty $f.PackagePath | Should -Be '1.sql' $f.Length | Should -Be 0 $f.Name | Should -BeNullOrEmpty $f.LastWriteTime | Should -BeNullOrEmpty $f.ByteArray | Should -BeNullOrEmpty $f.Hash | Should -BeNullOrEmpty $f.Parent | Should -BeNullOrEmpty } It "Should create new DBOpsFile object from fileobject" { $f = [DBOpsFile]::new($fileObject1, '1.sql') $f | Should -Not -BeNullOrEmpty $f.PackagePath | Should -Be '1.sql' $f.Length | Should -BeGreaterThan 0 $f.Name | Should -Be '1.sql' $f.LastWriteTime | Should -Not -BeNullOrEmpty $f.ByteArray | Should -Not -BeNullOrEmpty $f.Hash | Should -BeNullOrEmpty $f.Parent | Should -BeNullOrEmpty #Negative tests { [DBOpsFile]::new(([System.IO.FileInfo]$null), $script1, '1.sql') } | Should -Throw 'Empty path name is not legal' { [DBOpsFile]::new($fileObject1, '') } | Should -Throw 'Path inside the package cannot be empty' } It "Should create new hash-protected DBOpsFile" { $f = [DBOpsFile]::new($fileObject1, '1.sql', $true) $f | Should -Not -BeNullOrEmpty $f.PackagePath | Should -Be '1.sql' $f.Length | Should -BeGreaterThan 0 $f.Name | Should -Be '1.sql' $f.LastWriteTime | Should -Not -BeNullOrEmpty $f.ByteArray | Should -Not -BeNullOrEmpty $f.Hash | Should -Not -BeNullOrEmpty $f.Protected | Should -Be $true $f.Parent | Should -BeNullOrEmpty } It "Should create new hash-protected DBOpsFile and validate hash" { $hash = [DBOpsHelper]::ToHexString([Security.Cryptography.HashAlgorithm]::Create("MD5").ComputeHash([DBOpsHelper]::GetBinaryFile($script1))) $f = [DBOpsFile]::new($fileObject1, '1.sql', $hash) $f | Should -Not -BeNullOrEmpty $f.PackagePath | Should -Be '1.sql' $f.Length | Should -BeGreaterThan 0 $f.Name | Should -Be '1.sql' $f.LastWriteTime | Should -Not -BeNullOrEmpty $f.ByteArray | Should -Not -BeNullOrEmpty $f.Hash | Should -Be $hash $f.Protected | Should -Be $true $f.Parent | Should -BeNullOrEmpty #Negative tests { [DBOpsFile]::new($fileObject1, '1.sql', '0xf00') } | Should -Throw 'File cannot be loaded, hash mismatch' { [DBOpsFile]::new($fileObject1, '1.sql', '') } | Should -Throw 'File cannot be loaded, hash mismatch' { [DBOpsFile]::new($fileObject1, '1.sql', 'foo') } | Should -Throw 'File cannot be loaded, hash mismatch' } It "Should create new DBOpsFile object from zipfile using custom object" { $p = [DBOpsPackage]::new() $f1 = [DBOpsFile]::new($fileObject1, 'success\1.sql', $true) $p.NewBuild('1.0').AddScript($f1) $p.SaveToFile($packageName) #Open zip file stream $writeMode = [System.IO.FileMode]::Open try { $stream = [FileStream]::new($packageName, $writeMode) #Open zip file $zip = [ZipArchive]::new($stream, [ZipArchiveMode]::Read) try { $zipEntry = $zip.Entries | Where-Object FullName -eq (Join-PSFPath -Normalize 'content\1.0\success\1.sql') # testing unprotected files $f = [DBOpsFile]::new($zipEntry, '1.sql') $f | Should -Not -BeNullOrEmpty $f.PackagePath | Should -Be '1.sql' $f.Length | Should -BeGreaterThan 0 $f.Name | Should -Be '1.sql' $f.LastWriteTime | Should -Not -BeNullOrEmpty $f.ByteArray | Should -Not -BeNullOrEmpty $f.Hash | Should -BeNullOrEmpty $f.Parent | Should -BeNullOrEmpty # testing protected files $f = [DBOpsFile]::new($zipEntry, '1.sql', $f1.Hash) $f | Should -Not -BeNullOrEmpty $f.PackagePath | Should -Be '1.sql' $f.Length | Should -BeGreaterThan 0 $f.Name | Should -Be '1.sql' $f.LastWriteTime | Should -Not -BeNullOrEmpty $f.ByteArray | Should -Not -BeNullOrEmpty $f.Hash | Should -Be $f1.Hash $f.Parent | Should -BeNullOrEmpty # negative testing { [DBOpsFile]::new($zipEntry, '1.sql', '0xf00') } | Should -Throw 'File cannot be loaded, hash mismatch' { [DBOpsFile]::new($zipEntry, '1.sql', '') } | Should -Throw 'File cannot be loaded, hash mismatch' { [DBOpsFile]::new($zipEntry, '1.sql', 'foo') } | Should -Throw 'File cannot be loaded, hash mismatch' } catch { throw $_ } finally { #Close archive $zip.Dispose() } } catch { throw $_ } finally { #Close archive $stream.Dispose() } } } Context "tests other DBOpsFile methods" { BeforeEach { $pkg = [DBOpsPackage]::new() $build = $pkg.NewBuild('1.0') $pkg.SaveToFile($packageName, $true) $file = [DBOpsFile]::new($fileObject1, (Join-PSFPath -Normalize 'success\1.sql'), $true) $cFile = [DBOpsFile]::new($fileObject1, 'whatever.ps1') $build.AddFile($file, 'Scripts') $pkg.AddFile($cfile, 'PreDeployFile') $pkg.Alter() } AfterAll { if (Test-Path $packageName) { Remove-Item $packageName } } It "should test ToString method" { $file.ToString() | Should -Be (Join-PSFPath -Normalize 'success\1.sql') $cfile.ToString() | Should -Be 'whatever.ps1' } It "should test RebuildHash method" { $oldHash = $file.Hash $file.Hash = '' $file.RebuildHash() $file.Hash | Should -Be $oldHash } It "should test ValidateHash method" { $hash = $file.Hash { $file.ValidateHash('foo') } | Should -Throw 'File cannot be loaded, hash mismatch' { $file.ValidateHash($hash) } | Should -Not -Throw } It "should test GetDeploymentPath method" { $file.GetDeploymentPath() | Should -Be '1.0\success\1.sql' $cFile.GetDeploymentPath() | Should -Be 'whatever.ps1' } It "should test GetPackagePath method" { $file.GetPackagePath() | Should -Be (Join-PSFPath -Normalize 'content\1.0\success\1.sql') $cFile.GetPackagePath() | Should -Be 'whatever.ps1' } It "should test GetContent method" { $file.GetContent() | Should -BeLike 'CREATE TABLE a (a int)*' $cFile.GetContent() | Should -BeLike 'CREATE TABLE a (a int)*' #ToDo: add files with different encodings } It "should test SetContent method" { $oldData = $file.ByteArray $oldHash = $file.Hash $file.SetContent([DBOpsHelper]::GetBinaryFile($script2)) $file.ByteArray | Should -Not -Be $oldData $file.ByteArray | Should -Not -BeNullOrEmpty $file.Hash | Should -Not -Be $oldHash $file.Hash | Should -Not -BeNullOrEmpty } It "should test ExportToJson method" { $j = $file.ExportToJson() | ConvertFrom-Json $j.PackagePath | Should -Be (Join-PSFPath -Normalize 'success\1.sql') $j.Hash | Should -Be ([DBOpsHelper]::ToHexString([Security.Cryptography.HashAlgorithm]::Create("MD5").ComputeHash([DBOpsHelper]::GetBinaryFile($script1)))) } It "should test Save method" { #Save old file parameters $oldResults = Get-ArchiveItem $packageName | Where-Object Path -eq (Join-PSFPath -Normalize 'content\1.0\success\1.sql') $oldResults2 = Get-ArchiveItem $packageName | Where-Object Path -eq (Join-PSFPath -Normalize 'whatever.ps1') #Sleep 2 seconds to ensure that modification date is changed Start-Sleep -Seconds 2 #Modify file content $file.SetContent([DBOpsHelper]::GetBinaryFile($script2)) #Open zip file stream $writeMode = [System.IO.FileMode]::Open $stream = [FileStream]::new($packageName, $writeMode) try { #Open zip file $zip = [ZipArchive]::new($stream, [ZipArchiveMode]::Update) try { #Initiate saving { $file.Save($zip) } | Should -Not -Throw { $cFile.Save($zip) } | Should -Not -Throw } catch { throw $_ } finally { #Close archive $zip.Dispose() } } catch { throw $_ } finally { #Close archive $stream.Dispose() } $testResults = Get-ArchiveItem $packageName | Where-Object Path -eq (Join-PSFPath -Normalize 'content\1.0\success\1.sql') $oldResults.LastWriteTime -lt ($testResults | Where-Object Path -eq $oldResults.Path).LastWriteTime | Should -Be $true $testResults = Get-ArchiveItem $packageName | Where-Object Path -eq 'whatever.ps1' $oldResults2.LastWriteTime -lt ($testResults | Where-Object Path -eq $oldResults2.Path).LastWriteTime | Should -Be $true # { $p = [DBOpsPackage]::new($packageName) } | Should -Throw #Because of the hash mismatch - package file is not updated in Save() } It "should test Alter method" { #Save old file parameters $oldResults = Get-ArchiveItem $packageName | Where-Object Path -eq (Join-PSFPath -Normalize 'content\1.0\success\1.sql') $oldResults2 = Get-ArchiveItem $packageName | Where-Object Path -eq (Join-PSFPath -Normalize 'whatever.ps1') #Sleep 2 seconds to ensure that modification date is changed Start-Sleep -Seconds 2 #Modify file content $file.SetContent([DBOpsHelper]::GetBinaryFile($script2)) { $file.Alter() } | Should -Not -Throw { $cFile.Alter() } | Should -Not -Throw $testResults = Get-ArchiveItem $packageName | Where-Object Path -eq (Join-PSFPath -Normalize 'content\1.0\success\1.sql') $oldResults.LastWriteTime -lt ($testResults | Where-Object Path -eq $oldResults.Path).LastWriteTime | Should -Be $true $testResults = Get-ArchiveItem $packageName | Where-Object Path -eq 'whatever.ps1' $oldResults2.LastWriteTime -lt ($testResults | Where-Object Path -eq $oldResults2.Path).LastWriteTime | Should -Be $true } } } |