Source code

Revision control

Copy as Markdown

Other Tools

Unicode true↩
; Tests use the silent install feature to bypass message box prompts.↩
SilentInstall silent↩
; This is the executable that will be run by an xpcshell test↩
OutFile "test_stub_installer.exe"↩
; The executable will write output to this file, and the xpcshell test↩
; will read the contents of the file to determine whether the tests passed↩
!define TEST_OUTPUT_FILENAME .\test_installer_output.txt↩
!include "stub_shared_defs.nsh"↩
; Some variables used only by tests and mocks↩
Var Stdout↩
Var FailureMessage↩
Var TestBreakpointNumber↩
; For building the test exectuable, this version of the IsTestBreakpointSet macro↩
; checks the value of the TestBreakpointNumber. For real installer executables,↩
; this macro is empty, and does nothing. (See stub.nsi for the that version.)↩
!macro IsTestBreakpointSet breakpointNumber↩
${If} ${breakpointNumber} == $TestBreakpointNumber↩
Return↩
${EndIf}↩
!macroend↩
!include "LogicLib.nsh"↩
!include "FileFunc.nsh"↩
!include "TextFunc.nsh"↩
!include "WinVer.nsh"↩
!include "WordFunc.nsh"↩
Function ExitProcess↩
FunctionEnd↩
Function AttachConsole↩
; NSIS doesn't attach a console to the installer, so we'll do that now↩
System::Call 'kernel32::AttachConsole(i -1)i.r0'↩
${If} $0 != 0↩
; Windows STD_OUTPUT_HANDLE is defined as -11↩
System::Call 'kernel32::GetStdHandle(i -11)i.r0'↩
Push $0↩
${Else}↩
; If there's no console, exit with a nonzero exit code↩
System::Call 'kernel32::ExitProcess(i 65536)'↩
${EndIf}↩
FunctionEnd↩
; ${AtLeastWin10} is a macro provided by WinVer.nsh that can act as the predicate of a LogicLib↩
; control statement. This macro redefinition makes this test mockable↩
Var MockAtLeastWin10↩
!define /redef AtLeastWin10 `$MockAtLeastWin10 IsMockedAsTrue ""`↩
; See stub.nsi for the real version of CheckCpuSupportsSSE↩
Var MockCpuHasSSE↩
Function CheckCpuSupportsSSE↩
StrCpy $CpuSupportsSSE "$MockCpuHasSSE"↩
FunctionEnd↩
; See stub.nsi for the real version of CanWrite↩
Var MockCanWrite↩
Function CanWrite↩
StrCpy $CanWriteToInstallDir $MockCanWrite↩
FunctionEnd↩
!macro _IsMockedAsTrue _v _b _t _f↩
; If the mock value is the same as 'true', jump to the label specified in $_t↩
; Otherwise, jump to the label specified in $_f↩
; (This is compatible with LogicLib ${If} and similar tests)↩
StrCmp `${_v}` 'true' `${_t}` `${_f}`↩
!macroend↩
; A helpful macro for testing that a variable is equal to a value.↩
; Provide the variable name (bare, without $ prefix) and the expected value.↩
; For example, to test that $MyVariable is equal to "hello there", you would write:↩
; !insertmacro AssertEqual MyVariable "hello there"↩
!macro AssertEqual _variableName _expectedValue↩
${If} $${_variableName} != ${_expectedValue}↩
StrCpy $FailureMessage "At Line ${__LINE__}: Expected ${_variableName} of ${_expectedValue} , got $${_variableName}"↩
SetErrors↩
Return↩
${EndIf}↩
!macroend↩
Var TestFailureCount↩
!macro UnitTest _testFunctionName↩
Call ${_testFunctionName}↩
IfErrors 0 +3↩
IntOp $TestFailureCount $TestFailureCount + 1↩
FileWrite $Stdout "FAILURE: $FailureMessage; "↩
ClearErrors↩
!macroend↩
; Redefine ElevateUAC as a no-op in this test exectuable↩
!define /redef ElevateUAC ``↩
!include stub.nsh↩
; .onInit is responsible for running the tests↩
Function .onInit↩
Call AttachConsole↩
Pop $Stdout↩
IntOp $TestFailureCount 0 + 0↩
!insertmacro UnitTest TestDontInstallOnOldWindows↩
!insertmacro UnitTest TestDontInstallOnNewWindowsWithoutSSE↩
!insertmacro UnitTest TestDontInstallOnOldWindowsWithoutSSE↩
!insertmacro UnitTest TestGetArchToInstall↩
!insertmacro UnitTest TestMaintServiceCfg↩
!insertmacro UnitTest TestCanWriteToDirSuccess↩
!insertmacro UnitTest TestCanWriteToDirFail↩
${If} $TestFailureCount = 0↩
; On success, write the success metric and jump to the end↩
FileWrite $Stdout "All stub installer tests passed"↩
${Else}↩
FileWrite $Stdout "$TestFailureCount stub installer tests failed"↩
${EndIf}↩
FileClose $Stdout↩
Return↩
OnError:↩
Abort "Failed to run tests."↩
FunctionEnd↩
; Expect installation to abort if windows version < 10↩
Function TestDontInstallOnOldWindows↩
StrCpy $MockAtLeastWin10 'false'↩
StrCpy $MockCpuHasSSE '1'↩
StrCpy $AbortInstallation ''↩
StrCpy $ExitCode "Unknown"↩
Call CommonOnInit↩
!insertmacro AssertEqual ExitCode "${ERR_PREINSTALL_SYS_OS_REQ}"↩
!insertmacro AssertEqual AbortInstallation "true"↩
!insertmacro AssertEqual R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG)"↩
FunctionEnd↩
; Expect installation to abort on processor without SSE, WIndows 10+ version↩
Function TestDontInstallOnNewWindowsWithoutSSE↩
StrCpy $MockAtLeastWin10 'true'↩
StrCpy $MockCpuHasSSE '0' ↩
StrCpy $AbortInstallation ''↩
StrCpy $ExitCode "Unknown"↩
Call CommonOnInit↩
!insertmacro AssertEqual ExitCode "${ERR_PREINSTALL_SYS_HW_REQ}"↩
!insertmacro AssertEqual AbortInstallation "true"↩
FunctionEnd↩
; Expect installation to abort on processor without SSE, Windows <10 version↩
Function TestDontInstallOnOldWindowsWithoutSSE↩
StrCpy $MockAtLeastWin10 'false'↩
StrCpy $MockCpuHasSSE '0' ↩
StrCpy $AbortInstallation ''↩
StrCpy $ExitCode "Unknown"↩
Call CommonOnInit↩
!insertmacro AssertEqual ExitCode "${ERR_PREINSTALL_SYS_OS_REQ}"↩
!insertmacro AssertEqual AbortInstallation "true"↩
!insertmacro AssertEqual R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)"↩
FunctionEnd↩
; Expect to find a known supported architecture for Windows↩
Function TestGetArchToInstall↩
StrCpy $TestBreakpointNumber "${TestBreakpointArchToInstall}"↩
StrCpy $MockAtLeastWin10 'true'↩
StrCpy $MockCpuHasSSE '1'↩
StrCpy $INSTDIR "Unknown"↩
StrCpy $ArchToInstall "Unknown"↩
Call CommonOnInit↩
${Switch} $ArchToInstall↩
${Case} "${ARCH_X86}"↩
; OK, fall through↩
${Case} "${ARCH_AMD64}"↩
; OK, fall through↩
${Case} "${ARCH_AARCH64}"↩
; OK↩
${Break}↩
${Default}↩
StrCpy $FailureMessage "Unexpected value for ArchToInstall: $ArchToInstall"↩
SetErrors↩
Return↩
${EndSwitch}↩
${Switch} $INSTDIR↩
${Case} "${DefaultInstDir64bit}"↩
; OK, fall through↩
${Case} "${DefaultInstDir32bit}"↩
; OK↩
${Break}↩
${Default}↩
StrCpy $FailureMessage "Unexpected value for INSTDIR: $INSTDIR"↩
SetErrors↩
Return↩
${EndSwitch}↩
FunctionEnd↩
; Since we're not actually elevating permissions, expect not to enable installing maintenance service↩
Function TestMaintServiceCfg↩
StrCpy $TestBreakpointNumber "${TestBreakpointMaintService}"↩
StrCpy $CheckboxInstallMaintSvc 'Unknown'↩
StrCpy $MockAtLeastWin10 'true'↩
StrCpy $MockCpuHasSSE '1'↩
Call CommonOnInit↩
!insertmacro AssertEqual CheckboxInstallMaintSvc "0"↩
FunctionEnd↩
; Expect success if we can write to installation directory↩
Function TestCanWriteToDirSuccess↩
StrCpy $TestBreakpointNumber "${TestBreakpointCanWriteToDir}"↩
StrCpy $MockCanWrite 'true'↩
StrCpy $MockAtLeastWin10 'true'↩
StrCpy $MockCpuHasSSE '1'↩
StrCpy $CanWriteToInstallDir "Unknown"↩
StrCpy $AbortInstallation "false"↩
Call CommonOnInit↩
; Since we're not running as admin, expect directory to be under user's own home directory, so it should be writable↩
!insertmacro AssertEqual CanWriteToInstallDir "true"↩
!insertmacro AssertEqual AbortInstallation "false"↩
FunctionEnd↩
; Expect failure if we can't write to installation directory↩
Function TestCanWriteToDirFail↩
StrCpy $TestBreakpointNumber "${TestBreakpointCanWriteToDir}"↩
StrCpy $MockCanWrite 'false'↩
StrCpy $MockAtLeastWin10 'true'↩
StrCpy $MockCpuHasSSE '1'↩
StrCpy $CanWriteToInstallDir "Unknown"↩
StrCpy $AbortInstallation "false"↩
Call CommonOnInit↩
; Since we're not running as admin, expect directory to be under user's own home directory, so it should be writable↩
!insertmacro AssertEqual CanWriteToInstallDir "false"↩
!insertmacro AssertEqual ExitCode "${ERR_PREINSTALL_NOT_WRITABLE}"↩
!insertmacro AssertEqual AbortInstallation "true"↩
FunctionEnd↩
Section↩
SectionEnd↩