This is an automated email from the ASF dual-hosted git repository. leginee pushed a commit to branch bazel-migration in repository https://gitbox.apache.org/repos/asf/openoffice.git
commit db9514d4d88722b66b4c8337b6b32ae0890a1fe4 Author: Peter Kovacs <[email protected]> AuthorDate: Sat Aug 1 16:29:30 2026 +0200 test(sal,shell): wire the osl/socket + shell zip suites; two reusable test hooks Nine more suites onto `bazel test`. The headline is that "these need a CppUnit external dep" — carried in the frontier and main/test/readme.md for months — was simply wrong: every one of them is a plain GoogleTest suite. Nothing checked so far actually uses CppUnit. //main/sal osl_SocketOld, osl_Socket_tests, osl_StreamSocket, osl_DatagramSocket, osl_SocketAddr, osl_Socket2, osl_ConnectorSocket, osl_AcceptorSocket (8, from qa/osl/socket/makefile.mk; all they needed was ws2_32) //main/shell shell_qa_zip (3 cases) — zipfile reader over a real .odt. dmake split this into exe + DLL only so the DLL could be rebuilt against a different STL (NO_DEFAULT_STL); no analogue here, so both TUs go into the one exe. Two reusable hooks fell out, both plumbed through gtest_test: * //build/testsupport:sal_process_init. The socket suites each declare their own bare main() instead of going through SAL_IMPLEMENT_MAIN, and on Windows that macro is what calls sal_detail_initialize() -> WSAStartup (sal3.dll's DllMain only ever calls the matching WSACleanup, never WSAStartup). Without it Winsock is never initialised and every osl socket call returns WSANOTINITIALISED, so the suites collapse in ways that implicate everything except the cause — SocketAddr constructors quietly yield unusable addresses, getLocalHostname() fails. These are testshl2-era suites; that harness used to supply main() for them. The shim initialises from a dynamic initialiser (run by the CRT before main) using __argc/__argv, since osl_setCommandArgs asserts argc > 0. It is migration-authored test support, not AOO source, hence build/ rather than main/<module>/qa/. * gtest_test's data_files. Staging a fixture beside the exe is NOT enough: `bazel test` sets the working directory to the execroot, not the exe's dir. Co-located DLLs still resolve (the loader searches the exe's own path), which makes it easy to assume relative opens do too. shell_qa_zip opens "simpledocument.odt" by bare name and threw file-not-found while passing when run by hand from the staged dir. data_files stages the input AND switches the target to a .bat launcher that cd's there first, forwarding the exit code. With the shim, 4 of the 8 socket suites are fully green and the rest go from near-total failure to a small residual set, none of it a build problem. The module's own .xsce files already excluded connect_003 and getLocalHost_001 for wntmsci — our exact platform — plus ctors_family_Ipx and getHostname_002 everywhere; the remainder need Administrator (raw sockets), use an unsupported socket option (SO_DONTROUTE), or depend on DNS. All 8 are added to sal_tests per that suite's stated policy of running everything and treating failures as information; it is 44 targets / 34 passing, documented in main/test/readme.md. Also recorded there and in CLAUDE.md: writerfilter/qa/cppunittests is misnamed — only doctok is GoogleTest, the other four use the retired testshl harness, as does sal/qa/rtl_strings, which its own readme.txt marks superseded by qa/rtl/{ostring,oustring} (both already wired). Dead weight, not blockers. Co-Authored-By: Claude Opus 5 <[email protected]> --- CLAUDE.md | 27 ++++++++++--- build/rules/gtest_test.bzl | 40 +++++++++++++++++-- build/testsupport/BUILD.bazel | 16 ++++++++ build/testsupport/sal_process_init.cxx | 64 ++++++++++++++++++++++++++++++ main/sal/BUILD.bazel | 53 +++++++++++++++++++++++++ main/shell/BUILD.bazel | 33 ++++++++++++++++ main/test/readme.md | 71 +++++++++++++++++++++++++++++++--- 7 files changed, 289 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 63959e4f30..1e11722886 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,12 +49,27 @@ test 🔨 C++ unit-test infra runnable — NOW THE FRONT-LINE TASK: br id 1, now linked into every gtest_test exe) not just staged as an external <exe>.manifest, or late DLL loads fall outside the activation context. NEXT: sweep qa/ across the remaining migrated - modules — most of what is left is NOT standalone: svl/qa/complex + - svtools/qa/unoapi + sfx2 + writerfilter/qa/complex are Java/UNO, - svl/qa/test_URIHelper and configmgr/qa/unit bootstrap a UNO - component context, shell/qa + writerfilter/qa/cppunittests are - cppunit. So the front line now shifts to the two fixtures: - OfficeConnection (running-soffice) and a CppUnit external dep. + modules. DONE since: 8 sal osl/socket suites + shell_qa_zip. + "Needs a CppUnit external dep" was largely a MYTH — NOTHING checked + so far actually uses cppunit. osl/socket and shell/qa are plain + GoogleTest (now wired); writerfilter/qa/cppunittests is misnamed — + only doctok is GoogleTest, the other 4 (odiapi/qname/sl/xxml) use + the RETIRED testshl harness, as does rtl_strings, which is also + superseded by qa/rtl/{ostring,oustring} — treat all of those as dead + weight, not blockers, and do not migrate them. Two reusable hooks came + out of it, both in gtest_test: //build/testsupport:sal_process_init + (suites with a bare main() skip SAL_IMPLEMENT_MAIN ⇒ no WSAStartup + ⇒ every osl socket call is WSANOTINITIALISED) and data_files (a + staged fixture is NOT enough — bazel test's CWD is the execroot, so + relative opens need the cd-first .bat launcher). NEXT: what is + genuinely left is not standalone — svl/qa/complex + svtools/qa/unoapi + + sfx2 + writerfilter/qa/complex are Java/UNO; svl/qa/test_URIHelper, + configmgr/qa/unit and cppuhelper/qa/propertysetmixin bootstrap a UNO + component context. So the front line is now ONE fixture: + OfficeConnection (running-soffice). test.dll is built and its + arg plumbing is rtl::Bootstrap "arg-soffice=path:…"/"arg-user=…", + so the missing piece is a rule that points it at //main/staging:install + and gives the test exe its own UNO bootstrap. testtools ⬜ (bridgetest — pure-C++ UNO bridge round-trip; cli/pyuno/java variants need rules_java — see Java bucket) qadevOOo 🔨 OOoRunner.jar built (//main/qadevOOo:OOoRunner — qadevOOo QA diff --git a/build/rules/gtest_test.bzl b/build/rules/gtest_test.bzl index 0cde3d9fcb..9217f857be 100644 --- a/build/rules/gtest_test.bzl +++ b/build/rules/gtest_test.bzl @@ -75,10 +75,33 @@ def _staged_gtest_test_impl(ctx): ctx.actions.symlink(output = man, target_file = ctx.file.app_manifest) staged.append(man) + # Co-locating a data file with the exe is not enough for a test that opens it + # by bare relative name: `bazel test` runs the executable with the working + # directory set to the execroot, not to the exe's directory (the loader finds + # the staged DLLs via the exe's own path, which is why those work regardless). + # When run_in_staged_dir is set, hand Bazel a .bat that cd's into the staged + # dir first and forwards the exit code, so relative paths resolve there. + executable = staged_exe + if ctx.attr.run_in_staged_dir: + launcher = ctx.actions.declare_file(d + "/" + ctx.label.name + "_run.bat") + ctx.actions.write( + output = launcher, + content = "\r\n".join([ + "@echo off", + 'cd /d "%~dp0" || exit /b 1', + '"%~dp0' + staged_exe.basename + '" %*', + "exit /b %ERRORLEVEL%", + "", + ]), + is_executable = True, + ) + staged.append(launcher) + executable = launcher + return [DefaultInfo( - executable = staged_exe, + executable = executable, runfiles = ctx.runfiles(files = staged), - files = depset([staged_exe]), + files = depset([executable]), )] _staged_gtest_test = rule( @@ -89,6 +112,7 @@ _staged_gtest_test = rule( "runtime": attr.label_list(allow_files = True), "companions": attr.label_list(cfg = "target"), "app_manifest": attr.label(allow_single_file = True, default = _APP_MANIFEST), + "run_in_staged_dir": attr.bool(default = False), }, ) @@ -106,12 +130,19 @@ def gtest_test( copts = [], defines = [], runtime_dlls = [], + data_files = [], companions = [], additional_linker_inputs = [], linkopts = [], size = "small", **kwargs): - """A GoogleTest suite that actually runs under `bazel test` on Windows/MD.""" + """A GoogleTest suite that actually runs under `bazel test` on Windows/MD. + + data_files: inputs the test opens by relative path (fixture documents, …). + They are staged beside the exe AND the test is launched with its working + directory set to that staged dir, which co-location alone does not give you + (see run_in_staged_dir in the staging rule). + """ cc_binary( name = name + "_bin", srcs = srcs, @@ -135,7 +166,8 @@ def gtest_test( _staged_gtest_test( name = name, binary = ":" + name + "_bin", - runtime = runtime_dlls + [_CRT], + runtime = runtime_dlls + data_files + [_CRT], companions = companions, + run_in_staged_dir = bool(data_files), size = size, ) diff --git a/build/testsupport/BUILD.bazel b/build/testsupport/BUILD.bazel new file mode 100644 index 0000000000..5643a9325b --- /dev/null +++ b/build/testsupport/BUILD.bazel @@ -0,0 +1,16 @@ +package(default_visibility = ["//visibility:public"]) + +# Bazel migration test support — helper TUs linked into test exes. These are +# migration-authored (like //main/bridges:jni_test_launcher), NOT AOO product +# source, which is why they live under build/ rather than main/<module>/qa/. + +# sal_process_init — runs sal_detail_initialize() from a dynamic initialiser, +# for GoogleTest suites whose own main() skips the SAL_IMPLEMENT_MAIN +# boilerplate. On Windows that boilerplate is what calls WSAStartup(), so +# without it every osl socket call fails with WSANOTINITIALISED. See the file +# header for the full story. +# +# Exported as a plain source file rather than a cc_library so it compiles with +# the consuming test's own copts/defines (the sal/qa suites need /Zc:wchar_t- +# and the sal_qa_test define set to agree with sal3.dll). +exports_files(["sal_process_init.cxx"]) diff --git a/build/testsupport/sal_process_init.cxx b/build/testsupport/sal_process_init.cxx new file mode 100644 index 0000000000..00a85cfdfb --- /dev/null +++ b/build/testsupport/sal_process_init.cxx @@ -0,0 +1,64 @@ +/************************************************************** + * + * 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. + * + *************************************************************/ + +// Bazel migration test support — NOT part of the AOO product source. +// +// Every real AOO binary enters through SAL_IMPLEMENT_MAIN (sal/main.h), whose +// generated main() calls sal_detail_initialize() first. On Windows that is +// where WSAStartup() happens (sal/osl/w32/salinit.cxx) — sal3.dll's DllMain +// only ever calls the matching WSACleanup(), never WSAStartup(). +// +// Several sal/qa GoogleTest suites (qa/osl/socket/*) declare a plain +// int main(int argc, char ** argv) { InitGoogleTest(...); RUN_ALL_TESTS(); } +// which skips that boilerplate, so Winsock is never initialised and every osl +// socket call fails with WSANOTINITIALISED — SocketAddr constructors silently +// produce unusable addresses, getLocalHostname() fails, and the suite reports +// dozens of unrelated-looking assertion failures. They date from the testshl2 +// era, when the harness supplied main() (and the init) for them; testshl2 was +// retired, and nothing took over the job. +// +// Fixing the suites would mean editing product-adjacent source, which is out of +// scope for this migration. Instead this TU is linked into those test exes and +// does the initialisation from a dynamic initialiser, which the CRT runs BEFORE +// main(). __argc/__argv are already populated at that point (the MSVC CRT sets +// them during startup, ahead of dynamic initialisers), so sal sees the real +// command line exactly as SAL_IMPLEMENT_MAIN would pass it — osl_setCommandArgs +// asserts argc > 0, so passing 0/NULL is not an option. +// +// Deliberately NOT calling sal_detail_deinitialize(): sal3.dll's DllMain already +// issues WSACleanup() on DLL_PROCESS_DETACH, and a second one would unbalance +// the Winsock refcount. + +#include <stdlib.h> // __argc / __argv + +#include "sal/main.h" + +namespace { + +struct SalProcessInit { + SalProcessInit() { sal_detail_initialize(__argc, __argv); } +}; + +// Dynamic initialiser: constructed before main(), like the CRT startup that +// SAL_IMPLEMENT_MAIN would otherwise front. +SalProcessInit theSalProcessInit; + +} diff --git a/main/sal/BUILD.bazel b/main/sal/BUILD.bazel index f471f2f380..bd001a851f 100644 --- a/main/sal/BUILD.bazel +++ b/main/sal/BUILD.bazel @@ -268,6 +268,51 @@ sal_qa_test(name = "osl_old_test_file", srcs = ["qa/osl/file/osl_old_test_file.c # osl_Thread calls Win32 Sleep() (kernel32, default-linked): force-include <windows.h>. sal_qa_test(name = "osl_Thread", srcs = ["qa/osl/process/osl_Thread.cxx"], subdir = "osl/process", copts = ["/FIwindows.h"]) +# osl/socket — 8 apps from qa/osl/socket/makefile.mk. These were long listed as +# "blocked on a CppUnit external dep"; that was wrong — every one of them is +# already a plain GoogleTest suite (`#include "gtest/gtest.h"`, TEST_F) with no +# testshl2 include, so all they ever needed was ws2_32. 6 of the 8 share +# sockethelper.cxx (ping/hostname/addr helpers). +# +# These bind real sockets on localhost and resolve the local hostname, so unlike +# the rest of sal/qa they are environment-sensitive by nature. +# +# //build/testsupport:sal_process_init is REQUIRED, not incidental: each of +# these suites declares its own bare main() that skips the SAL_IMPLEMENT_MAIN +# boilerplate, and on Windows that boilerplate (sal_detail_initialize) is what +# calls WSAStartup. Without it Winsock is never initialised, every osl socket +# call returns WSANOTINITIALISED, and the suites fail wholesale in ways that +# point everywhere except the real cause. They are testshl2-era suites — that +# harness used to supply main() for them. +_SOCKET_LINKOPTS = ["ws2_32.lib"] + +_SOCKET_INIT = "//build/testsupport:sal_process_init.cxx" + +sal_qa_test(name = "osl_SocketOld", srcs = ["qa/osl/socket/osl_Socket.cxx", _SOCKET_INIT], subdir = "osl/socket", linkopts = _SOCKET_LINKOPTS) +sal_qa_test(name = "osl_Socket_tests", srcs = ["qa/osl/socket/osl_Socket_tests.cxx", _SOCKET_INIT], subdir = "osl/socket", linkopts = _SOCKET_LINKOPTS) + +[ + sal_qa_test( + name = t, + srcs = [ + "qa/osl/socket/%s.cxx" % t, + "qa/osl/socket/sockethelper.cxx", + "qa/osl/socket/sockethelper.hxx", + _SOCKET_INIT, + ], + subdir = "osl/socket", + linkopts = _SOCKET_LINKOPTS, + ) + for t in [ + "osl_StreamSocket", + "osl_DatagramSocket", + "osl_SocketAddr", + "osl_Socket2", + "osl_ConnectorSocket", + "osl_AcceptorSocket", + ] +] + # systools — Win32 COM smart pointers (needs ole32 + CoInitialize). sal_qa_test(name = "test_comtools", srcs = ["qa/systools/test_comtools.cxx"], subdir = "systools", copts = ["/FIwindows.h"], linkopts = ["ole32.lib"]) @@ -339,6 +384,14 @@ test_suite( ":tcwf", ":osl_old_test_file", ":osl_Thread", + ":osl_SocketOld", + ":osl_Socket_tests", + ":osl_StreamSocket", + ":osl_DatagramSocket", + ":osl_SocketAddr", + ":osl_Socket2", + ":osl_ConnectorSocket", + ":osl_AcceptorSocket", ":test_comtools", ":testHelperFunctions", ":sal_ut_types", diff --git a/main/shell/BUILD.bazel b/main/shell/BUILD.bazel index 2c7055de0d..9bac4cd55f 100644 --- a/main/shell/BUILD.bazel +++ b/main/shell/BUILD.bazel @@ -2,6 +2,7 @@ package(default_visibility = ["//visibility:public"]) load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") load("//build/rules:lngconvex_rule.bzl", "lngconvex_bundle") +load("//build/rules:gtest_test.bzl", "gtest_test") # ── Common settings ─────────────────────────────────────────────── # Defines shared by all shlxthandler targets (XML parser + ZIP reader @@ -438,5 +439,37 @@ cc_binary( visibility = ["//visibility:public"], ) +# ── qa unit test ────────────────────────────────────────────────── +# zipfile reader round-trip over a real .odt (qa/zip). Another suite long +# filed as "needs CppUnit" that is in fact plain GoogleTest. +# +# dmake built this as an exe (ziptest.obj) linking a DLL (qa_zipimpl.dll from +# testzipimpl.obj); that split existed only to let the DLL be rebuilt against a +# different STL (NO_DEFAULT_STL / msvcprt.lib in testimpl/makefile.mk), which +# has no analogue here — so both TUs go straight into the one exe. +# +# The test opens "simpledocument.odt" by BARE RELATIVE NAME, so it needs the +# file resolvable from the process's working directory — which `bazel test` sets +# to the execroot, not the exe's dir. Passing it as data_files both stages it +# beside the exe and switches the target to the cd-first .bat launcher. +gtest_test( + name = "shell_qa_zip", + srcs = [ + "qa/zip/ziptest.cxx", + "qa/zip/testimpl/testzipimpl.cxx", + "qa/zip/testimpl/testzipimpl.hxx", + ], + copts = _SHLXT_COPTS + ["/Imain/shell/qa/zip"], + defines = _SHLXT_DEFINES, + deps = [ + ":zipfile", + "//main/sal:sal_headers", + ], + additional_linker_inputs = ["//main/sal:sal_implib"], + linkopts = ["$(execpath //main/sal:sal_implib)"], + runtime_dlls = ["//main/sal:sal3"], + data_files = ["qa/zip/simpledocument.odt"], +) + exports_files(glob(["**/*.component"])) diff --git a/main/test/readme.md b/main/test/readme.md index a4372343fb..7157875f45 100644 --- a/main/test/readme.md +++ b/main/test/readme.md @@ -28,7 +28,8 @@ holdouts). This brings the test layer onto Bazel so suites run under | Piece | Path | Role | | ----- | ---- | ---- | | `@gtest` | `ext_libraries/modules/gtest/1.7.0/` | GoogleTest 1.7.0 bzlmod wrap (zip cached in `ext_sources`). Built with `/Zc:wchar_t-` so its `wchar_t` ABI matches `sal_Unicode` test code. | -| `gtest_test` rule | [//build/rules:gtest_test.bzl](../../build/rules/gtest_test.bzl) | Reusable runnable-test rule. The `/MD` toolchain embeds no manifest, so a bare `cc_test` exe can't launch (DLLs land in runfiles subdirs; loose CRT → R6034). This stages the exe + runtime DLLs + VC90 CRT + an external `<exe>.manifest` into ONE flat dir (the test analog of `//main/idl:svidl_bundle`). | +| `gtest_test` rule | [//build/rules:gtest_test.bzl](../../build/rules/gtest_test.bzl) | Reusable runnable-test rule. The `/MD` toolchain embeds no manifest, so a bare `cc_test` exe can't launch (DLLs land in runfiles subdirs; loose CRT → R6034). This stages the exe + runtime DLLs + VC90 CRT + an external `<exe>.manifest` into ONE flat dir (the test analog of `//main/idl:svidl_bundle`). Pass `data_files` for fixture inputs the test opens by relative path — see "working directory" below. | +| `sal_process_init` | [//build/testsupport](../../build/testsupport/BUILD.bazel) | Migration-authored TU that runs `sal_detail_initialize()` from a dynamic initialiser, for suites whose own `main()` skips the `SAL_IMPLEMENT_MAIN` boilerplate (⇒ no `WSAStartup`). | | `libtest` | [//main/test:test](BUILD.bazel) | `test.dll` — `test::OfficeConnection` + arg/url helpers, for *subsequent* (UNO) tests that bootstrap a running soffice over URP. Built; not yet exercised. | | `vc90_app_manifest_res` | [//main/external/msvcp90](../external/msvcp90/BUILD.bazel) | The VC90-CRT manifest compiled to a `.res` and linked into every `gtest_test` exe at `RT_MANIFEST` id 1. See "the CRT activation context" below. | | `sal_qa_test` macro | [//main/sal:sal_qa.bzl](../sal/sal_qa.bzl) | Thin `gtest_test` wrapper for the sal/qa suites (common copts/deps + per-dir `*_Const.h` include). | @@ -49,6 +50,9 @@ holdouts). This brings the test layer onto Bazel so suites run under `:cppuhelper_qa_unourl`, `:cppuhelper_qa_weak` - `//main/binaryurp:binaryurp_tests` — `:binaryurp_qa_cache`, `:binaryurp_qa_unmarshal` + - `//main/shell:shell_qa_zip` (3) — zipfile reader over a real `.odt` + - `//main/sal:osl_Socket_tests`, `:osl_StreamSocket`, `:osl_DatagramSocket`, + `:osl_AcceptorSocket` (4 of the 8 socket suites; see the socket note below) **Tests with private IDL types** (cppu/qa has a `types.idl` defining Enum1/Struct1/Interface1/… used only by the tests): reuse the `idl_library` @@ -109,6 +113,17 @@ holdouts). This brings the test layer onto Bazel so suites run under (Not yet handled: under `--compilation_mode=dbg` the exes link `/MDd` but this `.res` still carries the *release* CRT manifest.) +- **Staging a data file beside the exe is not enough — the working directory is + the execroot.** `bazel test` launches the test with its CWD set to the + execroot, *not* the exe's directory. Co-located DLLs still resolve (the loader + searches the exe's own path), which makes it easy to assume relative file + opens will too — they don't. A test that opens a fixture by bare relative name + (`//main/shell:shell_qa_zip` → `simpledocument.odt`) throws + file-not-found while passing when run by hand from the staged dir. Pass such + inputs as `data_files`: they are staged beside the exe *and* the target + switches to a `.bat` launcher that `cd`s there first and forwards the exit + code. + - **`/Zc:wchar_t-` must be consistent across gtest and every test TU.** gtest declares `PrintTo(wchar_t)`; with `/Zc:wchar_t-` (`wchar_t == unsigned short`) on one side only, that mangles vs `PrintTo(unsigned short)` → `LNK2019`. Fixed @@ -127,11 +142,11 @@ holdouts). This brings the test layer onto Bazel so suites run under ## The sal suite is deliberately NOT a green gate -`//main/sal:sal_tests` runs **every** migrated self-contained sal/qa test — 36 +`//main/sal:sal_tests` runs **every** migrated self-contained sal/qa test — 44 targets, passing and failing alike, on the principle that failures are information, not something to hide (the rationale lives next to the `test_suite` in [main/sal/BUILD.bazel](../sal/BUILD.bazel)). So expect it to be -red. As of 2026-08-01, 30 pass and these 6 fail, each on its **own merits** — +red. As of 2026-08-01, 34 pass and these 10 fail, each on its **own merits** — none is a build or loader problem, and the source is out of scope: | Target | Failing | Why | @@ -142,6 +157,45 @@ none is a build or loader problem, and the source is out of scope: | `rtl_logfile` | 1 | Writes/reads `c:/temp` and asserts on it — env/permission bound | | `osl_Thread` | 1 | `resume_001` is a timing race; flaky, not deterministic | | `rtl_OUString2` | 1 | `convertFromString` expects `\x80` to fail UTF-8 validation — test-data drift, same class as `rtl_textcvt` | +| `osl_SocketOld` | 10 | see socket note below | +| `osl_SocketAddr` | 3 | see socket note below | +| `osl_Socket2` | 7 | see socket note below | +| `osl_ConnectorSocket` | 1 | see socket note below | + +### The osl/socket suites + +Long recorded as "blocked on a CppUnit external dep" — that was simply wrong. +All 8 apps in `qa/osl/socket/makefile.mk` are plain GoogleTest suites with no +testshl2 include; they only ever needed `ws2_32`. + +What they *did* need is `//build/testsupport:sal_process_init.cxx`. Each +declares its own bare `main()` instead of going through `SAL_IMPLEMENT_MAIN`, +and on Windows that macro is what calls `sal_detail_initialize()` → +**`WSAStartup()`** (sal3.dll's `DllMain` only ever calls the matching +`WSACleanup()`, never `WSAStartup`). Without it Winsock is never initialised, +every osl socket call returns `WSANOTINITIALISED`, and the suites collapse in +ways that implicate everything except the real cause — `SocketAddr` +constructors quietly yield unusable addresses, `getLocalHostname()` fails. +These are testshl2-era suites; that harness used to supply `main()` for them. +The shim does the init from a dynamic initialiser (which the CRT runs before +`main`), using `__argc`/`__argv` — `osl_setCommandArgs` asserts `argc > 0`. + +With it, 4 of the 8 are fully green (`osl_Socket_tests`, `osl_StreamSocket`, +`osl_DatagramSocket`, `osl_AcceptorSocket`) and the rest go from +near-total failure to a small residual set — none of it a build problem: + +- **Upstream already knew.** `connect_003` and `getLocalHost_001` are listed in + the module's own `.xsce` exclusion files *specifically for `wntmsci`*, our + exact platform; `ctors_family_Ipx` (IPX is dead on modern Windows) and + `getHostname_002` are excluded on every platform. +- **Needs Administrator.** `ctors_TypeRaw` / `getType_003` create a + `osl_Socket_TypeRaw` socket — privileged on Windows. The test's own message + admits it doesn't pass on Linux/Solaris either. +- **Unsupported socket option.** `setOption_001` / `getOption_simple_001` set + `SO_DONTROUTE`; the test even comments "maybe asAcceptorSocket is not right + initialized". +- **DNS/host dependent.** `getHostname_001`, `getSocketAddrHandle_002`, + `getLocalPort_002` resolve names against whatever network the machine is on. Earlier revisions of this file listed `rtl_str`/`rtl_ustr`/`rtl_string` as NULL-deref crashes; those were since fixed (boundary checks in the tests plus @@ -150,8 +204,15 @@ NULL-deref crashes; those were since fixed (boundary checks in the tests plus (`osl_Security` is not in the suite at all — it fails to *build* on testshl2, see the gotcha above; it is unwired entirely, not an exclusion.) -Still unwired: cppunit suites (`osl/socket`, `rtl_strings`) → need a CppUnit -external dep; child-process tests (`osl/process`, `rtl/bootstrap`, +`rtl_strings` was also filed under "needs CppUnit". It does not: it includes +`testshl/tresstatewrapper.hxx`, i.e. the retired **testshl** harness, and its own +`readme.txt` says it is "the old test implementation of rtl::XString", +superseded by `sal/qa/rtl/ostring` + `sal/qa/rtl/oustring` — both of which are +already wired (`rtl_OString2`, `rtl_str`, `rtl_string`, `rtl_OUString2`, +`rtl_ustr`). So it is **dead weight, not a blocker**; there is nothing to gain +by migrating it. + +Still unwired: child-process tests (`osl/process`, `rtl/bootstrap`, `rtl/process`) → they resolve their helper exe via `getExecutablePath()`+`"/../bin"` (the dmake `solver/bin` layout), which flat Bazel staging can't satisfy without source changes — `gtest_test` has a `companions` hook ready for when that layout
