diff --git a/.github/workflows/macos_tests.yaml b/.github/workflows/macos_tests.yaml index 1c3547d96..4dde326aa 100644 --- a/.github/workflows/macos_tests.yaml +++ b/.github/workflows/macos_tests.yaml @@ -13,6 +13,8 @@ jobs: env: CONFIGURE_OPTS: --prefix=/tmp/modules --with-loadedmodules=null:dot --with-tcl=/opt/homebrew/lib --with-tclsh=/opt/homebrew/bin/tclsh COVERAGE: y + EXTRA_SCRIPT_PRETEST: make install-testsiteconfig-1 && export TESTSUITE_ENABLE_SITECONFIG=1 + EXTRA_SCRIPT_POSTTEST: unset TESTSUITE_ENABLE_SITECONFIG steps: - uses: actions/checkout@v6 with: @@ -30,8 +32,15 @@ jobs: make - name: Test Modules build run: | + # specific compiling to enable DYLD library insertion + for f in lib/testutil-*.c; do + n=$(basename "$f" .c) + clang -dynamiclib -arch arm64 -arch arm64e -o lib/lib${n}.dylib lib/${n}.c + done + eval $EXTRA_SCRIPT_PRETEST make test-deps script/mt + eval $EXTRA_SCRIPT_POSTTEST - name: Install Modules run: | make install diff --git a/.hunspell.en.dic b/.hunspell.en.dic index 0c40f8703..a6f852e95 100644 --- a/.hunspell.en.dic +++ b/.hunspell.en.dic @@ -1334,3 +1334,5 @@ YYYYMMDD roadmap CI GHA +ts +OSX diff --git a/lib/testutil-0getgroups.c b/lib/testutil-0getgroups.c index 8786a1be6..e4fdc0656 100644 --- a/lib/testutil-0getgroups.c +++ b/lib/testutil-0getgroups.c @@ -1,7 +1,7 @@ /************************************************************************* * * TESTUTIL-GETGROUPS.C, Superseded getgroups function for test purpose - * Copyright (C) 2020-2021 Xavier Delaruelle + * Copyright (C) 2020-2026 Xavier Delaruelle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ int getgroups(int size, gid_t list[]) { - return 0; + return 0; } /* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */ diff --git a/lib/testutil-closedir.c b/lib/testutil-closedir.c index 0a6e3374a..f985b3212 100644 --- a/lib/testutil-closedir.c +++ b/lib/testutil-closedir.c @@ -1,7 +1,7 @@ /************************************************************************* * * TESTUTIL-CLOSEDIR.C, Superseded closedir function for test purpose - * Copyright (C) 2019-2021 Xavier Delaruelle + * Copyright (C) 2019-2026 Xavier Delaruelle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,9 +20,30 @@ #include +#if defined (__APPLE__) + +int my_closedir(DIR *dirp) +{ + return -1; +} + +/* Code injection with DYLD interposing */ +__attribute__((used)) +static struct { + const void *replacement; + const void *replacee; +} interposers[] +__attribute__((section("__DATA,__interpose"))) = { + { (const void *)my_closedir, (const void *)closedir } +}; + +#else + int closedir(DIR *dirp) { - return -1; + return -1; } +#endif + /* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */ diff --git a/lib/testutil-getgroups.c b/lib/testutil-getgroups.c index ee5acadbb..2b388dcbc 100644 --- a/lib/testutil-getgroups.c +++ b/lib/testutil-getgroups.c @@ -1,7 +1,7 @@ /************************************************************************* * * TESTUTIL-GETGROUPS.C, Superseded getgroups function for test purpose - * Copyright (C) 2020-2021 Xavier Delaruelle + * Copyright (C) 2020-2026 Xavier Delaruelle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ int getgroups(int size, gid_t list[]) { - return -1; + return -1; } /* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */ diff --git a/lib/testutil-getpwuid.c b/lib/testutil-getpwuid.c index 9a7522f7b..ceaa7125b 100644 --- a/lib/testutil-getpwuid.c +++ b/lib/testutil-getpwuid.c @@ -1,7 +1,7 @@ /************************************************************************* * * TESTUTIL-GETPWUID.C, Superseded getpwuid function for test purpose - * Copyright (C) 2020-2021 Xavier Delaruelle + * Copyright (C) 2020-2026 Xavier Delaruelle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,9 +21,30 @@ #include #include +#if defined (__APPLE__) + +struct passwd *my_getpwuid(uid_t uid) +{ + return NULL; +} + +/* Code injection with DYLD interposing */ +__attribute__((used)) +static struct { + const void *replacement; + const void *replacee; +} interposers[] +__attribute__((section("__DATA,__interpose"))) = { + { (const void *)my_getpwuid, (const void *)getpwuid } +}; + +#else + struct passwd *getpwuid(uid_t uid) { - return NULL; + return NULL; } +#endif + /* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */ diff --git a/lib/testutil-mktime.c b/lib/testutil-mktime.c index 2cc83605e..08d07e3b4 100644 --- a/lib/testutil-mktime.c +++ b/lib/testutil-mktime.c @@ -1,7 +1,7 @@ /************************************************************************* * * TESTUTIL-MKTIME.C, Superseded mktime function for test purpose - * Copyright (C) 2020-2021 Xavier Delaruelle + * Copyright (C) 2020-2026 Xavier Delaruelle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,9 +20,30 @@ #include +#if defined (__APPLE__) + +time_t my_mktime(struct tm *tm) +{ + return -1; +} + +/* Code injection with DYLD interposing */ +__attribute__((used)) +static struct { + const void *replacement; + const void *replacee; +} interposers[] +__attribute__((section("__DATA,__interpose"))) = { + { (const void *)my_mktime, (const void *)mktime } +}; + +#else + time_t mktime(struct tm *tm) { - return -1; + return -1; } +#endif + /* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */ diff --git a/lib/testutil-time.c b/lib/testutil-time.c index f76d04f1a..fe8d231b8 100644 --- a/lib/testutil-time.c +++ b/lib/testutil-time.c @@ -1,7 +1,7 @@ /************************************************************************* * * TESTUTIL-TIME.C, Superseded time function for test purpose - * Copyright (C) 2020-2021 Xavier Delaruelle + * Copyright (C) 2020-2026 Xavier Delaruelle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,9 +20,30 @@ #include +#if defined (__APPLE__) + +time_t my_time(time_t *tloc) +{ + return -1; +} + +/* Code injection with DYLD interposing */ +__attribute__((used)) +static struct { + const void *replacement; + const void *replacee; +} interposers[] +__attribute__((section("__DATA,__interpose"))) = { + { (const void *)my_time, (const void *)time } +}; + +#else + time_t time(time_t *tloc) { - return -1; + return -1; } +#endif + /* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */ diff --git a/testsuite/example/siteconfig.tcl-1 b/testsuite/example/siteconfig.tcl-1 index 32a89c582..87dee3b03 100644 --- a/testsuite/example/siteconfig.tcl-1 +++ b/testsuite/example/siteconfig.tcl-1 @@ -145,6 +145,11 @@ if {[info exists env(TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDGETPWUID)]} { if {[catch {initStateUsername} errMsg]} { reportError $errMsg } + if {$tcl_platform(os) eq "Darwin"} { + if {[catch {[initStateUsergroups]} errMsg]} { + reportError $errMsg + } + } } # test tcl ext lib procedures against a failed getgroups call diff --git a/testsuite/modules.00-init/120-siteconfig.exp b/testsuite/modules.00-init/120-siteconfig.exp index 387c5a75a..258bd3c3e 100644 --- a/testsuite/modules.00-init/120-siteconfig.exp +++ b/testsuite/modules.00-init/120-siteconfig.exp @@ -410,14 +410,22 @@ if {[info exists tclextlib_file]} { # test tcl ext lib procedures against a failed closedir call if {[info exists closedirlib_file] && [file exists $closedirlib_file]} { setenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDCLOSEDIR 1 - setenv_var LD_PRELOAD $closedirlib_file + if {$tcl_platform(os) ne "Darwin"} { + setenv_var LD_PRELOAD $closedirlib_file + } else { + setenv_var DYLD_INSERT_LIBRARIES $closedirlib_file + } set ans [list] - lappend ans "$error_msgs: couldn't close directory \"$modpathre\": Success" + lappend ans "$error_msgs: couldn't close directory \"$modpathre\": .*" lappend ans $vers_reportre testouterr_cmd_re sh -V OK [join $ans \n] unsetenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDCLOSEDIR - unsetenv_var LD_PRELOAD + if {$tcl_platform(os) ne "Darwin"} { + unsetenv_var LD_PRELOAD + } else { + unsetenv_var DYLD_INSERT_LIBRARIES + } } elseif {$verbose} { send_user "\tSkip tcl ext lib erroneous procedure calls as closedir test lib is not available\n" } @@ -425,18 +433,31 @@ if {[info exists closedirlib_file] && [file exists $closedirlib_file]} { # test tcl ext lib procedures against a failed getpwuid call if {[info exists getpwuidlib_file] && [file exists $getpwuidlib_file]} { setenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDGETPWUID 1 - setenv_var LD_PRELOAD $getpwuidlib_file + if {$tcl_platform(os) ne "Darwin"} { + setenv_var LD_PRELOAD $getpwuidlib_file + } else { + setenv_var DYLD_INSERT_LIBRARIES $getpwuidlib_file + } set ans [list] lappend ans "$error_msgs: couldn't find name for user id \"$userid\": .*" + if {$tcl_platform(os) eq "Darwin"} { + lappend ans "$error_msgs: couldn't find name for user id \"$userid\": .*" + } lappend ans $vers_reportre testouterr_cmd_re sh -V OK [join $ans \n] unsetenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDGETPWUID - unsetenv_var LD_PRELOAD + if {$tcl_platform(os) ne "Darwin"} { + unsetenv_var LD_PRELOAD + } else { + unsetenv_var DYLD_INSERT_LIBRARIES + } } elseif {$verbose} { send_user "\tSkip tcl ext lib erroneous procedure calls as getpwuid test lib is not available\n" } +# getgroups syscall is not used on Darwin +if {$tcl_platform(os) ne "Darwin"} { # test tcl ext lib procedures against a failed getgroups call if {[info exists getgroupslib_file] && [file exists $getgroupslib_file]} { setenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDGETGROUPS 1 @@ -481,18 +502,27 @@ if {[info exists dupgetgroupslib_file] && [file exists $dupgetgroupslib_file]} { } elseif {$verbose} { send_user "\tSkip tcl ext lib erroneous procedure calls as dupgetgroups test lib is not available\n" } +} # test tcl ext lib procedures against a failed time call if {[info exists timelib_file] && [file exists $timelib_file]} { setenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDTIME 1 - setenv_var LD_PRELOAD $timelib_file + if {$tcl_platform(os) ne "Darwin"} { + setenv_var LD_PRELOAD $timelib_file + } else { + setenv_var DYLD_INSERT_LIBRARIES $timelib_file + } set ans [list] lappend ans "$error_msgs: couldn't get Epoch time: .*" lappend ans $vers_reportre testouterr_cmd_re sh -V OK [join $ans \n] unsetenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDTIME - unsetenv_var LD_PRELOAD + if {$tcl_platform(os) ne "Darwin"} { + unsetenv_var LD_PRELOAD + } else { + unsetenv_var DYLD_INSERT_LIBRARIES + } } elseif {$verbose} { send_user "\tSkip tcl ext lib erroneous procedure calls as time test lib is not available\n" } @@ -508,14 +538,22 @@ unsetenv_var TESTSUITE_ENABLE_SITECONFIG_PARSEDATETIMEARG_NOARG # test tcl ext lib procedures against a failed mktime call if {[info exists mktimelib_file] && [file exists $mktimelib_file]} { setenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDMKTIME 1 - setenv_var LD_PRELOAD $mktimelib_file + if {$tcl_platform(os) ne "Darwin"} { + setenv_var LD_PRELOAD $mktimelib_file + } else { + setenv_var DYLD_INSERT_LIBRARIES $mktimelib_file + } set ans [list] lappend ans "$error_msgs: couldn't convert to Epoch time: .*" lappend ans $vers_reportre testouterr_cmd_re sh -V OK [join $ans \n] unsetenv_var TESTSUITE_ENABLE_SITECONFIG_TCLEXTLIBFAILEDMKTIME - unsetenv_var LD_PRELOAD + if {$tcl_platform(os) ne "Darwin"} { + unsetenv_var LD_PRELOAD + } else { + unsetenv_var DYLD_INSERT_LIBRARIES + } } elseif {$verbose} { send_user "\tSkip tcl ext lib erroneous procedure calls as mktime test lib is not available\n" }