ts: improve coverage of Tcl ext library on OSX
Some checks failed
easybuild-tests / framework (Tcl) (push) Has been cancelled
lint-tests / lint-all (push) Has been cancelled
linux-tests / tcl86-nolibtclenvmodules (push) Has been cancelled
linux-tests / tcl85-nolibtclenvmodules (push) Has been cancelled
linux-tests / tcl85-2 (push) Has been cancelled
linux-tests / tcl86 (push) Has been cancelled
linux-tests / tcl85 (push) Has been cancelled
linux-tests / tcl91 (push) Has been cancelled
linux-tests / tcl90 (push) Has been cancelled
linux-tests / el8 (push) Has been cancelled
linux-tests / el9 (push) Has been cancelled
macos-tests / macos (push) Has been cancelled
windows-tests / native-cmd (push) Has been cancelled
windows-tests / native-pwsh (push) Has been cancelled
windows-tests / cygwin (push) Has been cancelled
windows-tests / msys (push) Has been cancelled

Test Modules Tcl extended C library on Mac OSX against broken syscall
that are injected through DYLD, using its interposing mechanism [1].

[1] http://toves.freeshell.org/interpose/

Signed-off-by: Xavier Delaruelle <xavier.delaruelle@cea.fr>
This commit is contained in:
Xavier Delaruelle
2026-05-26 20:52:39 +02:00
parent facea59c9a
commit b46f00065e
10 changed files with 163 additions and 25 deletions

View File

@@ -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

View File

@@ -1334,3 +1334,5 @@ YYYYMMDD
roadmap
CI
GHA
ts
OSX

View File

@@ -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: */

View File

@@ -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 <dirent.h>
int closedir(DIR *dirp)
#if defined (__APPLE__)
int my_closedir(DIR *dirp)
{
return -1;
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;
}
#endif
/* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */

View File

@@ -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: */

View File

@@ -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 <stddef.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid)
#if defined (__APPLE__)
struct passwd *my_getpwuid(uid_t uid)
{
return NULL;
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;
}
#endif
/* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */

View File

@@ -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 <time.h>
time_t mktime(struct tm *tm)
#if defined (__APPLE__)
time_t my_mktime(struct tm *tm)
{
return -1;
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;
}
#endif
/* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */

View File

@@ -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 <time.h>
time_t time(time_t *tloc)
#if defined (__APPLE__)
time_t my_time(time_t *tloc)
{
return -1;
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;
}
#endif
/* vim:set tabstop=3 shiftwidth=3 expandtab autoindent: */

View File

@@ -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

View File

@@ -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"
}