THRIFT-5824 Migrate, refactor and improve Delphi code generation test script
Client: Delphi
Patch: Jens Geyer
diff --git a/.gitignore b/.gitignore
index e7f06a7..6a0495b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -211,7 +211,6 @@
/lib/delphi/**/*.local
/lib/delphi/**/*.dcu
/lib/delphi/**/*.2007
-/lib/delphi/**/codegen/*.bat
/lib/erl/.eunit
/lib/erl/.generated
/lib/erl/.rebar/
diff --git a/lib/delphi/test/codegen/README.md b/lib/delphi/test/codegen/README.md
index a014589..65fbe4e 100644
--- a/lib/delphi/test/codegen/README.md
+++ b/lib/delphi/test/codegen/README.md
@@ -1,28 +1,15 @@
+Prerequisites
+----------------------------------------------
+- a suitable dcc32.exe must be reachable via normal search path
+- the Thrift compiler thrift.exe is searched in this order
+ - under the `compiler` subdir, where debug is preferred over release
+ - otherwise via normal search path
+
How to use the test case:
----------------------------------------------
-- copy and the template batch file
-- open the batch file and adjust configuration as necessary
-- run the batch
+- run the POSH script
+- if any error messages occur, that's a bad sign
+- there may be known but unfixed issues, these are listed accordingly
-Configuration:
-----------------------------------------------
-SVNWORKDIR
-should point to the Thrift working copy root
-
-MY_THRIFT_FILES
-can be set to point to a folder with more thrift IDL files.
-If you don't have any such files, just leave the setting blank.
-
-BIN
-Local MSYS binary folder. Your THRIFT.EXE is installed here.
-
-MINGW_BIN
-Local MinGW bin folder. Contains DLL files required by THRIFT.EXE
-
-DCC
-Identifies the Delphi Command Line compiler (dcc32.exe)
-To be configuired only, if the default is not suitable.
-
-----------------------------------------------
-*EOF*
\ No newline at end of file
+*EOF*
diff --git a/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.bat.tmpl b/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.bat.tmpl
deleted file mode 100644
index 79cf0e3..0000000
--- a/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.bat.tmpl
+++ /dev/null
@@ -1,177 +0,0 @@
-REM /*
-REM * Licensed to the Apache Software Foundation (ASF) under one
-REM * or more contributor license agreements. See the NOTICE file
-REM * distributed with this work for additional information
-REM * regarding copyright ownership. The ASF licenses this file
-REM * to you under the Apache License, Version 2.0 (the
-REM * "License"); you may not use this file except in compliance
-REM * with the License. You may obtain a copy of the License at
-REM *
-REM * http://www.apache.org/licenses/LICENSE-2.0
-REM *
-REM * Unless required by applicable law or agreed to in writing,
-REM * software distributed under the License is distributed on an
-REM * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-REM * KIND, either express or implied. See the License for the
-REM * specific language governing permissions and limitations
-REM * under the License.
-REM */
-@echo off
-if ""=="%1" goto CONFIG
-goto HANDLEDIR
-
-REM -----------------------------------------------------
-:CONFIG
-REM -----------------------------------------------------
-
-rem * CONFIGURATION BEGIN
-rem * configuration settings, adjust as necessary to meet your system setup
-set SVNWORKDIR=
-set MY_THRIFT_FILES=
-set BIN=C:\MSys10\local\bin
-set MINGW_BIN=C:\MinGW\bin
-set DCC=
-set SUBDIR=gen-delphi
-rem * CONFIGURATION END
-
-
-REM -----------------------------------------------------
-:START
-REM -----------------------------------------------------
-
-rem * configured?
-if "%SVNWORKDIR%"=="" goto CONFIG_ERROR
-
-rem * try to find dcc32.exe
-echo Looking for dcc32.exe ...
-if not exist "%DCC%" set DCC=%ProgramFiles%\Embarcadero\RAD Studio\8.0\bin\dcc32.exe
-if not exist "%DCC%" set DCC=%ProgramFiles(x86)%\Embarcadero\RAD Studio\8.0\bin\dcc32.exe
-if not exist "%DCC%" goto CONFIG_ERROR
-echo Found %DCC%
-echo.
-
-rem * some helpers
-set PATH=%BIN%;%MINGW_BIN%;%PATH%
-set TARGET=%SVNWORKDIR%\..\thrift-testing
-set SOURCE=%SVNWORKDIR%
-set TESTAPP=TestProject
-set UNITSEARCH=%SOURCE%\lib\pas\src;%SOURCE%\lib\delphi\src
-set OUTDCU="%TARGET%\dcu"
-set LOGFILE=%TARGET%\%SUBDIR%\codegen.log
-
-rem * create and/or empty target dirs
-if not exist "%TARGET%" md "%TARGET%"
-if not exist "%TARGET%\%SUBDIR%" md "%TARGET%\%SUBDIR%"
-if not exist "%OUTDCU%" md "%OUTDCU%"
-if exist "%TARGET%\*.thrift" del "%TARGET%\*.thrift" /Q
-if exist "%TARGET%\%SUBDIR%\*.*" del "%TARGET%\%SUBDIR%\*.*" /Q
-if exist "%OUTDCU%\*.*" del "%OUTDCU%\*.*" /Q
-
-rem init logfile
-echo Errors > "%LOGFILE%"
-echo ---------------- >> "%LOGFILE%"
-
-rem * recurse through thrift WC and "my thrift files" folder
-rem * copies all .thrift files into thrift-testing
-call %0 %SOURCE%
-if not "%MY_THRIFT_FILES%"=="" call %0 %MY_THRIFT_FILES%
-
-rem * compile all thrift files, generate PAS and C++ code
-echo.
-echo Generating code, please wait ...
-cd "%TARGET%"
-for %%a in (*.thrift) do "%BIN%\thrift.exe" -v --gen delphi:register_types,constprefix,events,xmldoc "%%a" 2>> "%LOGFILE%"
-REM * for %%a in (*.thrift) do "%BIN%\thrift.exe" -v --gen cpp "%%a" >> NUL:
-cmd /c start notepad "%LOGFILE%"
-cd ..
-
-rem * check for special Delphi testcases being processed
-if not exist "%TARGET%\%SUBDIR%\ReservedKeywords.pas" goto TESTCASE_MISSING
-
-
-rem * generate a minimal DPR file that uses all generated pascal units
-cd "%TARGET%\%SUBDIR%\"
-if exist inherited.* ren inherited.* _inherited.*
-echo program %TESTAPP%; > %TESTAPP%.dpr
-echo {$APPTYPE CONSOLE} >> %TESTAPP%.dpr
-echo. >> %TESTAPP%.dpr
-echo uses >> %TESTAPP%.dpr
-for %%a in (*.pas) do echo %%~na, >> %TESTAPP%.dpr
-echo Windows, Classes, SysUtils; >> %TESTAPP%.dpr
-echo. >> %TESTAPP%.dpr
-echo begin >> %TESTAPP%.dpr
-echo Writeln('Successfully compiled!'); >> %TESTAPP%.dpr
-echo Writeln('List of units:'); >> %TESTAPP%.dpr
-for %%a in (*.pas) do echo Write('%%~na':30,'':10); >> %TESTAPP%.dpr
-echo Writeln; >> %TESTAPP%.dpr
-echo end. >> %TESTAPP%.dpr
-echo. >> %TESTAPP%.dpr
-cd ..\..
-
-rem * try to compile the DPR
-rem * this should not throw any errors, warnings or hints
-"%DCC%" -B "%TARGET%\%SUBDIR%\%TESTAPP%" -U"%UNITSEARCH%" -I"%UNITSEARCH%" -N"%OUTDCU%" -E"%TARGET%\%SUBDIR%"
-dir "%TARGET%\%SUBDIR%\%TESTAPP%.exe"
-if not exist "%TARGET%\%SUBDIR%\%TESTAPP%.exe" goto CODEGEN_FAILED
-echo.
-echo -----------------------------------------------------------------
-echo The compiled program is now executed. If it hangs or crashes, we
-echo have a serious problem with the generated code. Expected output
-echo is "Successfully compiled:" followed by a list of generated units.
-echo -----------------------------------------------------------------
-"%TARGET%\%SUBDIR%\%TESTAPP%.exe"
-echo -----------------------------------------------------------------
-echo.
-pause
-GOTO EOF
-
-REM -----------------------------------------------------
-:DXE_NOT_FOUND
-REM -----------------------------------------------------
-echo Delphi Compiler (dcc32.exe) not found.
-echo Please check the "DCC" setting in this batch.
-echo.
-cmd /c start notepad README.MD
-cmd /c start notepad %0
-pause
-GOTO EOF
-
-
-REM -----------------------------------------------------
-:CONFIG_ERROR
-REM -----------------------------------------------------
-echo Missing, incomplete or wrong configuration settings!
-cmd /c start notepad README.MD
-cmd /c start notepad %0
-pause
-GOTO EOF
-
-
-REM -----------------------------------------------------
-:TESTCASE_MISSING
-REM -----------------------------------------------------
-echo Missing an expected Delphi testcase!
-pause
-GOTO EOF
-
-
-REM -----------------------------------------------------
-:CODEGEN_FAILED
-REM -----------------------------------------------------
-echo Code generation FAILED!
-pause
-GOTO EOF
-
-
-REM -----------------------------------------------------
-:HANDLEDIR
-REM -----------------------------------------------------
-REM echo %1
-for /D %%a in (%1\*) do call %0 %%a
-if exist "%1\*.thrift" copy /b "%1\*.thrift" "%TARGET%\*.*"
-GOTO EOF
-
-
-REM -----------------------------------------------------
-:EOF
-REM -----------------------------------------------------
diff --git a/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.ps1 b/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.ps1
new file mode 100644
index 0000000..66f0b23
--- /dev/null
+++ b/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.ps1
@@ -0,0 +1,252 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+# *
+# http://www.apache.org/licenses/LICENSE-2.0
+# *
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+#---- failing tests --------------------------------------------
+
+# expected to fail at Thrift Compiler
+$FAIL_THRIFT = @(
+ "BrokenConstants.thrift", # intended to break
+ "DuplicateImportsTest.thrift", # subdir includes don't work here
+ "Include.thrift") # subdir includes don't work here
+
+# expected to fail at Delphi Compiler
+$FAIL_DELPHI = @()
+
+# unexpected but known bugs (TODO: fix them)
+$KNOWN_BUGS = @(
+ "ConstantsDemo.thrift",
+ "ConstOptionalField.thrift",
+ "IgnoreInitialismsTest.thrift",
+ "JavaTypes.thrift",
+ "JavaDefinitionOrderB.thrift",
+ "JavaDeepCopyTest.thrift",
+ "NameConflictTest.thrift",
+ "Types.thrift",
+ "Thrift5320.thrift",
+ "Service.thrift")
+
+
+
+#---- functions --------------------------------------------
+
+function FindThriftExe() {
+ # prefer debug over release over path
+ write-host -nonewline Looking for thrift.exe ...
+ $exe = "thrift.exe"
+
+ # if we have a freshly compiled one it might be a better choice
+ @("Release","Debug") | foreach{
+ if( test-path "$ROOTDIR\compiler\cpp\$_\thrift.exe") { $exe = "$ROOTDIR\compiler\cpp\$_\thrift.exe" }
+ if( test-path "$ROOTDIR\compiler\cpp\compiler\$_\thrift.exe") { $exe = "$ROOTDIR\compiler\cpp\$_\compiler\thrift.exe" }
+ }
+
+ return $exe
+}
+
+
+function FindDcc32Exe() {
+ # prefer debug over release over path
+ write-host -nonewline Looking for dcc32.exe ...
+ $exe = "dcc32.exe"
+
+ # TODO: add arbitraily complex code to locate a suitable dcc32.exe if it is not in the path
+
+ return $exe
+}
+
+
+function InitializeFolder([string] $folder, [string] $pattern) {
+ #write-host $folder\$pattern
+ if(-not (test-path $folder)) {
+ new-item $folder -type directory | out-null
+ }
+ pushd $folder
+ remove-item $pattern #-recurse
+ popd
+}
+
+
+function CopyFilesFrom([string] $source, $text) {
+ #write-host "$source"
+ if( ($source -ne "") -and (test-path $source)) {
+ if( $text -ne $null) {
+ write-host -foregroundcolor yellow Copying $text ...
+ }
+
+ pushd $source
+ # recurse dirs
+ gci . -directory | foreach {
+ CopyFilesFrom "$_"
+ }
+ # files within
+ gci *.thrift -file | foreach {
+ #write-host $_
+ $name = $_.name
+ copy-item $_ "$TARGET\$name"
+ }
+ popd
+ }
+}
+
+function TestIdlFile([string] $idl) {
+ # expected to fail at Thrift Compiler
+ $filter = $false
+ $FAIL_THRIFT | foreach {
+ if( $idl -eq $_) {
+ $filter = $true
+ write-host "Skipping $_"
+ }
+ }
+ if( $filter) { return $true }
+
+ # compile IDL
+ #write-host -nonewline " $idl"
+ InitializeFolder "$TARGET\gen-delphi" "*.pas"
+ &$THRIFT_EXE $VERBOSE -r --gen delphi:register_types,constprefix,events,xmldoc $idl | out-file "$TARGET\thrift.log"
+ if( -not $?) {
+ get-content "$TARGET\thrift.log" | out-default
+ write-host -foregroundcolor red "Thrift compilation failed: $idl"
+ return $false
+ }
+
+ # generate project dile
+ $units = gci "$TARGET\gen-delphi\*.pas"
+ $lines = @()
+ $lines += "program $TESTAPP;"
+ $lines += "{`$APPTYPE CONSOLE}"
+ $lines += ""
+ $lines += "uses"
+ $units | foreach { $name = $_.name.Replace(".pas",""); $lines += " $name," }
+ $lines += " Windows, Classes, SysUtils;"
+ $lines += ""
+ $lines += "begin"
+ $lines += " Writeln('Successfully compiled!');"
+ $lines += " Writeln('List of units:');"
+ $units | foreach { $name = $_.name.Replace(".pas",""); $lines += " Writeln('- $name');" }
+ $lines += " Writeln;"
+ $lines += ""
+ $lines += "end."
+ $lines += ""
+ $lines | set-content "$TARGET\gen-delphi\$TESTAPP.dpr"
+
+ # try to compile the DPR
+ # this should not throw any errors, warnings or hints
+ $exe = "$TARGET\gen-delphi\$TESTAPP.exe"
+ if( test-path $exe) { remove-item $exe }
+ &$DCC32_EXE -B "$TARGET\gen-delphi\$TESTAPP" -U"$UNITSEARCH" -I"$UNITSEARCH" -N"$OUTDCU" -E"$TARGET\gen-delphi" | out-file "$TARGET\compile.log"
+ if( -not (test-path $exe)) {
+
+ # expected to fail at Thrift Compiler
+ $filter = $false
+ $FAIL_DELPHI | foreach {
+ if( $idl -eq $_) {
+ $filter = $true
+ write-host ("Delphi compilation failed at "+$idl+" - as expected")
+ }
+ }
+ $KNOWN_BUGS | foreach {
+ if( $idl -eq $_) {
+ $filter = $true
+ write-host ("Delphi compilation failed at "+$idl+" - known issue (TODO)")
+ }
+ }
+ if( $filter) { return $true }
+
+ get-content "$TARGET\compile.log" | out-default
+ write-host -foregroundcolor red "Delphi compilation failed: $idl"
+ return $false
+ }
+
+ # The compiled program is now executed. If it hangs or crashes, we
+ # have a serious problem with the generated code. Expected output
+ # is "Successfully compiled:" followed by a list of generated units.
+ &"$exe" | out-file "$TARGET\exec.log"
+ if( -not $?) {
+ get-content "$TARGET\exec.log" | out-default
+ write-host -foregroundcolor red "Test execution failed: $idl"
+ return $false
+ }
+ return $true
+}
+
+#---- main -------------------------------------------------
+# CONFIGURATION BEGIN
+# configuration settings, adjust as necessary to meet your system setup
+$MY_THRIFT_FILES = ""
+$VERBOSE = "" # set any Thrift compiler debug/verbose flag you want
+
+# init
+$ROOTDIR = $PSScriptRoot + "\..\..\..\.."
+
+# try to find thrift.exe
+$THRIFT_EXE = FindThriftExe
+&$THRIFT_EXE -version
+if( -not $?) {
+ write-host -foregroundcolor red Missing thrift.exe
+ exit 1
+}
+
+# try to find dcc32.exe
+$DCC32_EXE = FindDcc32Exe
+&$DCC32_EXE --version
+if( -not $?) {
+ write-host -foregroundcolor red Missing dcc32.exe
+ exit 1
+}
+
+
+# some helpers
+$TARGET = "$ROOTDIR\..\thrift-testing"
+$TESTAPP = "TestProject"
+$UNITSEARCH = "$ROOTDIR\lib\pas\src;$ROOTDIR\lib\delphi\src"
+$OUTDCU = "$TARGET\dcu"
+
+# create and/or empty target dirs
+InitializeFolder "$TARGET" "*.thrift"
+InitializeFolder "$TARGET\gen-delphi" "*.pas"
+InitializeFolder "$OUTDCU" "*.dcu"
+
+# recurse through thrift WC and "my thrift files" folder
+# copies all .thrift files into thrift-testing
+CopyFilesFrom "$ROOTDIR" "Thrift IDL files"
+CopyFilesFrom "$MY_THRIFT_FILES" "Custom IDL files"
+
+# codegen and compile all thrift files, one by one to prevent side effects
+$count = 0
+write-host -foregroundcolor yellow Running codegen tests ..
+try {
+ pushd "$TARGET"
+ gci *.thrift -file | foreach {
+ $count += 1
+ $ok = TestIdlFile $_.name
+ if( -not $ok) {
+ throw "TEST FAILED" # automated tests
+ popd; pause; pushd "$TARGET" # interactive / debug
+ }
+ }
+ write-host -foregroundcolor green "Success ($count tests executed)"
+ exit 0
+} catch {
+ write-host -foregroundcolor red $_
+ exit 1
+} finally {
+ popd
+}
+
+#eof