[mapguide-commits] r10238 - in branches/4.0/MgDev: Bindings/src/Test/Java Bindings/src/Test/Java/extlib Bindings/src/Test/Java/src/org/osgeo/mapguide/test/common Bindings/src/Test/Php Oem/DWFTK/develop/global/src/dwfcore Web/src Web/src/HttpHandler Web/src/WebTestRunner
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Mon Nov 2 06:30:20 PST 2026
Author: jng
Date: 2026-11-02 06:30:19 -0800 (Mon, 02 Nov 2026)
New Revision: 10238
Added:
branches/4.0/MgDev/Bindings/src/Test/Java/extlib/libsqlite4java-linux-amd64.so
branches/4.0/MgDev/Web/src/WebTestRunner/CMakeLists.txt
Modified:
branches/4.0/MgDev/Bindings/src/Test/Java/README.txt
branches/4.0/MgDev/Bindings/src/Test/Java/src/org/osgeo/mapguide/test/common/CommonUtility.java
branches/4.0/MgDev/Bindings/src/Test/Php/TestContext.php
branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.cpp
branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.h
branches/4.0/MgDev/Web/src/CMakeLists.txt
branches/4.0/MgDev/Web/src/HttpHandler/OgcServer.cpp
Log:
#2493: Various fixes to support web tier test suite execution on Linux
Modified: branches/4.0/MgDev/Bindings/src/Test/Java/README.txt
===================================================================
--- branches/4.0/MgDev/Bindings/src/Test/Java/README.txt 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Bindings/src/Test/Java/README.txt 2026-11-02 14:30:19 UTC (rev 10238)
@@ -20,4 +20,25 @@
Unit tests results will be logged to unittest.log
-The default ant build.xml properties is configured for 64-bit release configuration of MapGuide. Where applicable, you should override these properties to match your specific build configuration.
\ No newline at end of file
+The default ant build.xml properties is configured for 64-bit release configuration of MapGuide. Where applicable, you should override these properties to match your specific build configuration.
+
+Running the tests on Linux
+==========================
+
+The suites read their .dump fixtures through sqlite4java, which needs a native library
+for the platform it runs on. The Windows ones are checked in under extlib/; the Linux one
+is libsqlite4java-linux-amd64.so, in the same directory, so the ant `dist` target copies it
+next to MgUnitTest.jar and it only has to be on java.library.path:
+
+ java -Djava.library.path=<dist>:<mapguide install>/webserverextensions/lib64 \
+ -jar MgUnitTest.jar <webconfig.ini> <log file>
+
+libsqlite4java-linux-amd64.so is the official 1.0.392 artifact for x86-64, taken from
+Maven Central (com.almworks.sqlite4java:libsqlite4java-linux-amd64:1.0.392, packaging
+"so"); its sha1 (5a97aa1b643252eb9be0901037cb440c2e145956) matches the one Maven Central
+publishes. SVN's default global-ignores matches *.so, so it has to be added with
+`svn add --force`.
+
+run_mapguide_tests.sh --tier web --web-suite java does all of this: it builds the runner
+with ant into a staged test pack, starts and stops the server, and reports the
+"Tests failed/run" summary.
Added: branches/4.0/MgDev/Bindings/src/Test/Java/extlib/libsqlite4java-linux-amd64.so
===================================================================
(Binary files differ)
Index: branches/4.0/MgDev/Bindings/src/Test/Java/extlib/libsqlite4java-linux-amd64.so
===================================================================
--- branches/4.0/MgDev/Bindings/src/Test/Java/extlib/libsqlite4java-linux-amd64.so 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Bindings/src/Test/Java/extlib/libsqlite4java-linux-amd64.so 2026-11-02 14:30:19 UTC (rev 10238)
Property changes on: branches/4.0/MgDev/Bindings/src/Test/Java/extlib/libsqlite4java-linux-amd64.so
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/x-sharedlib
\ No newline at end of property
Modified: branches/4.0/MgDev/Bindings/src/Test/Java/src/org/osgeo/mapguide/test/common/CommonUtility.java
===================================================================
--- branches/4.0/MgDev/Bindings/src/Test/Java/src/org/osgeo/mapguide/test/common/CommonUtility.java 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Bindings/src/Test/Java/src/org/osgeo/mapguide/test/common/CommonUtility.java 2026-11-02 14:30:19 UTC (rev 10238)
@@ -701,7 +701,11 @@
Console.WriteLine("Read path from current directory");
//System.out.println("Param (" + paramName+ "): " + str);
- String relPath = str.replaceAll("../../TestData", "").replaceAll("..\\\\..\\\\TestData", "");
+ // The dumps were recorded on Windows, so the relative path under TestData can
+ // use either separator. Normalising before stripping the prefix is not
+ // optional: the remainder below the prefix keeps its separators, and a
+ // backslash is not one on Linux.
+ String relPath = str.replace('\\', '/').replace("../../TestData", "");
String resolved = TestEnvConfiguration.resolveTestDataPath(relPath, true);
//System.out.println("Resolves to: " + resolved);
if (resolved != null)
Modified: branches/4.0/MgDev/Bindings/src/Test/Php/TestContext.php
===================================================================
--- branches/4.0/MgDev/Bindings/src/Test/Php/TestContext.php 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Bindings/src/Test/Php/TestContext.php 2026-11-02 14:30:19 UTC (rev 10238)
@@ -51,8 +51,12 @@
if (strlen($relPath) === 0) {
return Utils::GetPath($relPath);
}
+ // The dumps were recorded on Windows, so the relative path under TestData can use
+ // either separator. Normalising before stripping the prefix is not optional: the
+ // remainder below the prefix keeps its separators, and a backslash is not one on
+ // Linux.
+ $relPath = str_replace("\\", "/", $relPath);
$relPathFixed = str_replace("../../TestData", $this->testDataRootPath, $relPath);
- $relPathFixed = str_replace("..\\..\\TestData", $this->testDataRootPath, $relPathFixed);
return $relPathFixed;
}
public function getDataFilePath($relPath, $throwIfNotFound = true) {
Modified: branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.cpp
===================================================================
--- branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.cpp 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.cpp 2026-11-02 14:30:19 UTC (rev 10238)
@@ -24,8 +24,46 @@
#include "dwfcore/Exception.h"
using namespace DWFCore;
+// The message buffer is _zMessage[512]; one element is the terminator. Kept unsigned so the
+// bounded scan below compares like with like: MSVC builds this file at /W4, and the VC 8.0
+// project turns warnings into errors.
+#define _DWFCORE_EXCEPTION_MESSAGE_MAX_WCHARS 511u
+// Copy a message into the fixed buffer, always leaving a complete terminating null behind.
+//
+// The buffer holds 512 wide characters, so at most 511 are copied and _zMessage[511] is reserved
+// for the terminator. Zeroing "nBytes + 2" after the copy, which this used to do, does not
+// terminate the string: nBytes is always a multiple of sizeof(wchar_t), so the two zeroed bytes
+// land in the low half of the first wchar_t past the copy and the uninitialised high half makes
+// it non-zero. Every wcslen() on the message then runs off the end of the exception object - and
+// the first one to do so is the copy constructor below, reached by `throw e;` on a caught
+// exception (AddressSanitizer: heap-buffer-overflow in __interceptor_wcslen).
+//
+// The scan is bounded by the buffer's capacity rather than by wcslen(), so it cannot over-read
+// the source either: the source of a copy is another exception's buffer, which is the one this
+// code has to be able to trust.
+static void
+dwfCopyExceptionMessage( wchar_t* pBuffer, const wchar_t* zMessage )
+{
+ size_t nChars = 0;
+
+ if (zMessage != NULL)
+ {
+ while (nChars < _DWFCORE_EXCEPTION_MESSAGE_MAX_WCHARS && zMessage[nChars] != 0)
+ {
+ ++nChars;
+ }
+
+ if (nChars > 0)
+ {
+ DWFCORE_COPY_MEMORY( pBuffer, zMessage, nChars * sizeof(wchar_t) );
+ }
+ }
+
+ pBuffer[nChars] = 0;
+}
+
_DWFCORE_API
DWFException::DWFException( const wchar_t* zMessage,
const char* zFunction,
@@ -36,15 +74,7 @@
, _zFile( zFile )
, _nLine( nLine )
{
- _zMessage[0] = 0;
-
- if (zMessage)
- {
- size_t nBytes = min( 511*sizeof(wchar_t), DWFCORE_WIDE_STRING_LENGTH_IN_BYTES(zMessage) );
-
- DWFCORE_ZERO_MEMORY( _zMessage, nBytes + 2 );
- DWFCORE_COPY_MEMORY( _zMessage, zMessage, nBytes );
- }
+ dwfCopyExceptionMessage( _zMessage, zMessage );
}
_DWFCORE_API
@@ -61,15 +91,7 @@
, _zFile( rEx._zFile )
, _nLine( rEx._nLine )
{
- _zMessage[0] = 0;
-
- if (rEx._zMessage)
- {
- size_t nBytes = min( 511*sizeof(wchar_t), DWFCORE_WIDE_STRING_LENGTH_IN_BYTES(rEx._zMessage) );
-
- DWFCORE_ZERO_MEMORY( _zMessage, nBytes + 2 );
- DWFCORE_COPY_MEMORY( _zMessage, rEx._zMessage, nBytes );
- }
+ dwfCopyExceptionMessage( _zMessage, rEx._zMessage );
}
_DWFCORE_API
@@ -81,16 +103,8 @@
_zFile = rEx._zFile;
_nLine = rEx._nLine;
- _zMessage[0] = 0;
+ dwfCopyExceptionMessage( _zMessage, rEx._zMessage );
- if (rEx._zMessage)
- {
- size_t nBytes = min( 511*sizeof(wchar_t), DWFCORE_WIDE_STRING_LENGTH_IN_BYTES(rEx._zMessage) );
-
- DWFCORE_ZERO_MEMORY( _zMessage, nBytes + 2 );
- DWFCORE_COPY_MEMORY( _zMessage, rEx._zMessage, nBytes );
- }
-
return *this;
}
Modified: branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.h
===================================================================
--- branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.h 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Oem/DWFTK/develop/global/src/dwfcore/Exception.h 2026-11-02 14:30:19 UTC (rev 10238)
@@ -140,7 +140,8 @@
/// Constructor
///
///\param zMessage Describes the exception event.
- /// This string is copied into a local buffer and is limited to \b 512 wide characters.
+ /// This string is copied into a local buffer and is limited to \b 511 wide characters
+ /// plus a terminating null.
///\param zFunction The function in which the event occured. The \b __func__ macro is recommended.
///\param zFile The file in which the event occured. The \b __FILE__ macro is recommended.
///\param nLine The line number in the file in which the event occured. The \b __LINE__ macro is recommended.
Modified: branches/4.0/MgDev/Web/src/CMakeLists.txt
===================================================================
--- branches/4.0/MgDev/Web/src/CMakeLists.txt 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Web/src/CMakeLists.txt 2026-11-02 14:30:19 UTC (rev 10238)
@@ -7,6 +7,7 @@
add_subdirectory(HttpHandler)
if (NOT MG_COMMON_SUBSET_ONLY)
+ add_subdirectory(WebTestRunner)
add_subdirectory(DevHttpServer)
#add_subdirectory(CgiAgent)
Modified: branches/4.0/MgDev/Web/src/HttpHandler/OgcServer.cpp
===================================================================
--- branches/4.0/MgDev/Web/src/HttpHandler/OgcServer.cpp 2026-11-02 04:48:51 UTC (rev 10237)
+++ branches/4.0/MgDev/Web/src/HttpHandler/OgcServer.cpp 2026-11-02 14:30:19 UTC (rev 10238)
@@ -1612,8 +1612,10 @@
// Kill the UNICODE Byte Order Mark, if there is one.
if(pSlurp[0] == 0xfeff) {
- memcpy(pSlurp,pSlurp+1,iSizeInBytes);
- iSizeInBytes -= 2;
+ // The source and destination overlap by one CHARTYPE here, which memcpy does not allow;
+ // ASan stops the process on it (memcpy-param-overlap), which is how this was found.
+ memmove(pSlurp,pSlurp+1,iSizeInBytes);
+ iSizeInBytes -= sizeof(CHARTYPE);
}
// Make sure the thing is null-terminated.
Added: branches/4.0/MgDev/Web/src/WebTestRunner/CMakeLists.txt
===================================================================
--- branches/4.0/MgDev/Web/src/WebTestRunner/CMakeLists.txt (rev 0)
+++ branches/4.0/MgDev/Web/src/WebTestRunner/CMakeLists.txt 2026-11-02 14:30:19 UTC (rev 10238)
@@ -0,0 +1,49 @@
+find_package (JsonCpp REQUIRED)
+
+include_directories(${MG_OEM_CATCH2_INCLUDE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${MG_WEB_DIR}/src/HttpHandler
+ ${MG_WEB_DIR}/src/WebSupport
+ ${MG_WEB_DIR}/src/WebApp
+ ${MG_COMMON_DIR}/MdfModel
+ ${MG_COMMON_DIR}/MdfParser
+ ${MG_COMMON_DIR}/Foundation
+ ${MG_COMMON_DIR}/Geometry
+ ${MG_COMMON_DIR}/PlatformBase
+ ${MG_COMMON_DIR}/MapGuideCommon
+ ${ACE_INCLUDE_DIR}
+ ${XERCESC_INCLUDE_DIR}
+ ${JsonCpp_INCLUDE_DIR}
+ ${FDO_INCLUDE_DIR}
+)
+
+set(MgWebTestRunner_SRCS
+ GeoJsonTest.cpp
+ main.cpp
+ OgcTest.cpp
+ TestListener.cpp
+ WebLayoutTest.cpp
+)
+
+add_executable(MgWebTestRunner ${MgWebTestRunner_SRCS})
+add_sanitizers(MgWebTestRunner)
+set_target_properties( MgWebTestRunner
+ PROPERTIES OUTPUT_NAME "MgWebTestRunner" )
+
+target_link_libraries(MgWebTestRunner
+ ${ACE_LIBRARY}
+ ${XERCESC_LIBRARIES}
+ ${JsonCpp_LIBRARY}
+ MgWebSupport${MG_VERSION_SUFFIX}
+ MgHttpHandler${MG_VERSION_SUFFIX}
+ MgWebApp${MG_VERSION_SUFFIX}
+ MgMapGuideCommon${MG_VERSION_SUFFIX}
+ MgMdfParser${MG_VERSION_SUFFIX}
+ MgMdfModel${MG_VERSION_SUFFIX}
+ MgPlatformBase${MG_VERSION_SUFFIX}
+ MgFoundation${MG_VERSION_SUFFIX}
+ MgGeometry${MG_VERSION_SUFFIX}
+)
+
+# The suite reads its fixtures from TestData relative to the working directory
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/TestData DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
More information about the mapguide-commits
mailing list