Skip to content

Commit

Permalink
Release v2.1.0: Merge branch 'master' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
joeltimothyoh committed Sep 22, 2020
2 parents 83187a2 + fe8a900 commit ca2cf93
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 36 deletions.
91 changes: 62 additions & 29 deletions src/Compile-SourceScript/Public/Compile-SourceScript.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ function Compile-SourceScript {

# Initialize variables
$MOD = @{
# The sourcemod compiler returns exits code correctly.
# The sourcemod compiler wrapper returns the exit code of the lastmost executed shell statement. This is particularly bad when the compiler exits with '0' from a successful finalmost shell statement, even when one or more prior shell statements exited with non-zero exit codes.
# Hence, knowing that exit codes are not a reliable way to determine whether one or more compilation statements failed, we are going to use a regex on the stdout as a more reliable way to detect compilation errors, regardless of whether compilation was performed via the compiler binary or via the compiler wrapper.
sourcemod = @{
script_ext = '.sp'
plugin_ext = '.smx'
Expand All @@ -70,13 +73,18 @@ function Compile-SourceScript {
windows = @{
wrapper = 'compile.exe'
bin = 'spcomp.exe'
error_regex = '^Compilation aborted|^\d+\s+Errors?|.*\.sp\(\d+\)\s*:\s*(?:fatal)? error (\d+)'
}
others = @{
wrapper = 'compile.sh'
bin = 'spcomp'
error_regex = '^Compilation aborted|^\d+\s+Errors?|.*\.sp\(\d+\)\s*:\s*(?:fatal)? error (\d+)'
}
}
}
# The amxmodx compiler binary always exits with exit code 0.
# The amxmodx compiler wrapper always exits with exit code 0.
# Hence, knowing that exit codes are not a reliable way to determine whether one or more compilation statements failed, we are going to use a regex on the stdout as a more reliable way to detect compilation errors, regardless of whether compilation was performed via the compiler binary or via the compiler wrapper.
amxmodx = @{
script_ext = '.sma'
plugin_ext = '.amxx'
Expand All @@ -86,21 +94,18 @@ function Compile-SourceScript {
windows = @{
wrapper = 'compile.exe'
bin = 'amxxpc.exe'
error_regex = '^\d+\s+Errors?|compile failed|^.*\.sma\(\d+\)\s*:\s*error (\d+)'
}
others = @{
wrapper = 'compile.sh'
bin = 'amxxpc'
error_regex = '^\d+\s+Errors?|compile failed|^.*\.sma\(\d+\)\s*:\s*error (\d+)'
}
}
}
}
$COMPILER_NAME = if ($env:OS -eq 'Windows_NT') {
if ($PSBoundParameters['SkipWrapper']) { $MOD[$MOD_NAME]['compiler']['windows']['bin'] }
else { $MOD[$MOD_NAME]['compiler']['windows']['wrapper'] }
}else {
if ($PSBoundParameters['SkipWrapper']) { $MOD[$MOD_NAME]['compiler']['others']['bin'] }
else { $MOD[$MOD_NAME]['compiler']['others']['wrapper'] }
}
$OS = if ($env:OS -eq 'Windows_NT') { 'windows' } else { 'others' }
$COMPILER_NAME = if ($PSBoundParameters['SkipWrapper']) { $MOD[$MOD_NAME]['compiler'][$OS]['bin'] } else { $MOD[$MOD_NAME]['compiler'][$OS]['wrapper'] }
$SCRIPTING_DIR = $sourceFile.DirectoryName
$COMPILED_DIR = Join-Path $SCRIPTING_DIR $MOD[$MOD_NAME]['compiled_dir_name']
$COMPILER_PATH = Join-Path $SCRIPTING_DIR $COMPILER_NAME
Expand All @@ -123,33 +128,65 @@ function Compile-SourceScript {
# Get all items in compiled directory before compilation by hash
$compiledDirItemsPre = Get-ChildItem -Path $COMPILED_DIR -File -Recurse -Force | ? { $_.Extension -eq $MOD[$MOD_NAME]['plugin_ext'] } | Select-Object *, @{name='md5'; expression={(Get-FileHash -Path $_.Fullname -Algorithm MD5).Hash}}

# Prepare for compilation
"Compiling..." | Write-Host -ForegroundColor Cyan
# Generate command line arguments
$epoch = [Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s"))
$stdInFile = New-Item -Path (Join-Path $SCRIPTING_DIR ".$epoch") -ItemType File -Force
'1' | Out-File -FilePath $stdInFile.FullName -Force -Encoding utf8
$stdInFile = Join-Path $SCRIPTING_DIR ".$epoch"
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) (New-Guid).Guid
$stdoutFile = Join-Path $tempDir 'stdout'
$stderrFile = Join-Path $tempDir 'stderr'
$processArgs = @{
FilePath = $compiler.FullName
ArgumentList = @(
if ($PSBoundParameters['SkipWrapper']) {
$sourceFile.Name
"-o$($MOD[$MOD_NAME]['compiled_dir_name'])/$($sourceFile.Basename)$($MOD[$MOD_NAME]['plugin_ext'])"
}else {
$sourceFile.Name
}
)
WorkingDirectory = $SCRIPTING_DIR
RedirectStandardInput = $stdInFile.FullName
RedirectStandardInput = $stdInFile
RedirectStandardOutput = $stdoutFile
RedirectStandardError = $stderrFile
Wait = $true
NoNewWindow = $true
PassThru = $true
}
if ($PSBoundParameters['SkipWrapper']) {
$processArgs['ArgumentList'] = @(
$sourceFile.Name
"-o$($MOD[$MOD_NAME]['compiled_dir_name'])/$($sourceFile.Basename)$($MOD[$MOD_NAME]['plugin_ext'])"
)
}else {
$processArgs['ArgumentList'] = @(
$sourceFile.Name
)

try {
# Prepare compilation environment
if ($item = New-Item -Path $stdInFile -ItemType File -Force) {
# This dummy input bypasses the 'Press any key to continue' prompt of the compiler
'1' | Out-File -FilePath $item.FullName -Force -Encoding utf8
}
New-Item $tempDir -ItemType Directory -Force > $null
New-Item -Path $COMPILED_DIR -ItemType Directory -Force | Out-Null

# Begin compilation
"Compiling..." | Write-Host -ForegroundColor Cyan
if ($PSBoundParameters['SkipWrapper']) { "Compiling $($sourceFile.Name)..." | Write-Host -ForegroundColor Yellow }

# Compile
$global:LASTEXITCODE = 0
$p = Start-Process @processArgs
$stdout = Get-Content $stdoutFile
$stdout | Write-Host
$stderr = Get-Content $stderrFile
$stderr | Write-Host
foreach ($line in $stdout) {
if ($line -match $MOD[$MOD_NAME]['compiler'][$OS]['error_regex']) {
$global:LASTEXITCODE = 1
break
}
}
}catch {
throw
}finally {
# Cleanup
Remove-Item $stdInFile -Force
Remove-Item $tempDir -Recurse -Force
}
New-Item -Path $COMPILED_DIR -ItemType Directory -Force | Out-Null

# Begin compilation
if ($PSBoundParameters['SkipWrapper']) { "Compiling $($sourceFile.Name)..." | Write-Host -ForegroundColor Yellow }
Start-Process @processArgs
if ($PSBoundParameters['SkipWrapper']) { "End of compilation." | Write-Host -ForegroundColor Yellow }

# Get all items in compiled directory after compilation by hash
Expand Down Expand Up @@ -231,10 +268,6 @@ function Compile-SourceScript {
}catch {
Write-Error -Exception $_.Exception -Message $_.Exception.Message -Category $_.CategoryInfo.Category -TargetObject $_.TargetObject
}finally {
# Cleanup
if ($stdInFile) {
Remove-Item -Path $stdInFile -Force
}
"End of Compile-SourceScript." | Write-Host -ForegroundColor Cyan
}
}
Expand Down
6 changes: 6 additions & 0 deletions test/mod/amxmodx/addons/amxmodx/scripting/plugin1_bad.sma
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <amxmodx>

public plugin_init() {
log_message("Hello from amxmodx.");
}
i am junk
6 changes: 6 additions & 0 deletions test/mod/amxmodx/addons/amxmodx/scripting/plugin2_bad.sma
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <amxmodx>

public plugin_init() {
log_message("Hello from amxmodx.");
}
i am junk
6 changes: 6 additions & 0 deletions test/mod/sourcemod/addons/sourcemod/scripting/plugin1_bad.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <sourcemod>

public void OnPluginStart() {
LogMessage("Hello from sourcemod.");
}
i am junk
6 changes: 6 additions & 0 deletions test/mod/sourcemod/addons/sourcemod/scripting/plugin2_bad.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <sourcemod>

public void OnPluginStart() {
LogMessage("Hello from sourcemod.");
}
i am junk
7 changes: 4 additions & 3 deletions test/scripts/dep/Install-TestDependencies.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ try {
# Install Pester if needed
"Checking Pester version" | Write-Host
$pesterMinimumVersion = [version]'4.0.0'
$pesterMaximumVersion = [version]'4.10.1'
$pester = Get-Module 'Pester' -ListAvailable -ErrorAction SilentlyContinue
if (!$pester -or !($pester.Version -gt $pesterMinimumVersion)) {
if (!$pester -or !($pester | ? { $_.Version -ge $pesterMinimumVersion -and $_.Version -le $pesterMaximumVersion })) {
"Installing Pester" | Write-Host
Install-Module -Name 'Pester' -Repository 'PSGallery' -MinimumVersion $pesterMinimumVersion -Scope CurrentUser -Force
Install-Module -Name 'Pester' -Repository 'PSGallery' -MinimumVersion $pesterMinimumVersion -MaximumVersion $pesterMaximumVersion -Scope CurrentUser -Force
}
Get-Module Pester -ListAvailable
Get-Module Pester -ListAvailable | Out-String | Write-Verbose

if ($env:OS -ne 'Windows_NT') {
if ($IsLinux) {
Expand Down
51 changes: 47 additions & 4 deletions test/scripts/integration/Run-IntegrationTests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ $functionTestScriptBlock = {
for ($i=0; $i -le $iterations-1; $i++) {
"Iteration: $($i+1)" | Write-Host
& $script:cmd @cmdArgs
if ($global:LASTEXITCODE -ne $expectedExitCode) {
throw "Expected exit code $expectedExitCode but got exit code $global:LASTEXITCODE"
}
"Expected exit code: $expectedExitCode, Exit code: $global:LASTEXITCODE" | Write-Host -ForegroundColor Yellow
}
}catch {
$_ | Write-Error
Expand All @@ -28,30 +32,49 @@ $cmd = "Compile-SourceScript"
# SourceMod #
#############

"`n[sourcemod] Compile plugin via wrapper" | Write-Host
"`n[sourcemod] Compile plugin via wrapper, good plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin1.sp"
Force = $true
}
$iterations = 2
$expectedExitCode = 0
& $functionTestScriptBlock

"`n[sourcemod] Compile plugin via wrapper, bad plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin1_bad.sp"
Force = $true
}
$iterations = 2
$expectedExitCode = 1
& $functionTestScriptBlock

"`n[sourcemod] Compile plugin via compiler" | Write-Host
"`n[sourcemod] Compile plugin via compiler, good plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin2.sp"
Force = $true
SkipWrapper = $true
}
$iterations = 2
$expectedExitCode = 0
& $functionTestScriptBlock

"`n[sourcemod] Compile plugin via compiler, bad plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin2_bad.sp"
Force = $true
SkipWrapper = $true
}
$iterations = 2
$expectedExitCode = 1
& $functionTestScriptBlock

#############
# AMX Mod X #
#############

"`n[amxmodx] Compile plugin via wrapper" | Write-Host
"`n[amxmodx] Compile plugin via wrapper, good plugin" | Write-Host
# The following test should be run only for Windows, reason being that the non-Windows version:
# - Does not take in arguments, instead compiles all plugins within the scripting directory
# - Displays all the output using 'less' at the end of the compilation, thus is limited to interactive use
Expand All @@ -60,19 +83,39 @@ if ($env:OS -eq 'Windows_NT') {
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin1.sma"
Force = $true
}
$expectedExitCode = 0
$iterations = 2
& $functionTestScriptBlock

"`n[amxmodx] Compile plugin via wrapper, bad plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin1_bad.sma"
Force = $true
}
$expectedExitCode = 1
$iterations = 2
& $functionTestScriptBlock
}else { "Skipping: Test only applicable to Windows." | Write-Host }

"`n[amxmodx] Compile plugin via compiler" | Write-Host
"`n[amxmodx] Compile plugin via compiler, good plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin2.sma"
Force = $true
SkipWrapper = $true
}
$expectedExitCode = 0
$iterations = 2
& $functionTestScriptBlock

"`n[amxmodx] Compile plugin via compiler, bad plugin" | Write-Host
$cmdArgs = @{
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin2_bad.sma"
Force = $true
SkipWrapper = $true
}
$expectedExitCode = 1
$iterations = 2
& $functionTestScriptBlock

###########
# Results #
Expand Down

0 comments on commit ca2cf93

Please sign in to comment.