powerman has asked for the wisdom of the Perl Monks concerning the following question:

How to check is AF_UNIX available in reliable and cross-platform way?

Or, a little :) more general question: how to write reliable tests for platform-specific features (and is it have sense to do this)?

In Log::Fast test t/raise.t I'm trying to ensure exception will be thrown if user provide wrong custom path for syslog-type logging using UNIX sockets:

SKIP: { skip 'no UNIX sockets on Windows', 2 if $^O =~ /Win/; SKIP: { use Sys::Syslog (); my $path = Sys::Syslog::_PATH_LOG() || '/dev/log'; skip 'unable to detect syslog socket', 1 if !-S $path; lives_ok { $LOG->config({type=>'unix',path=>$path}) }; } throws_ok { $LOG->config({type=>'unix',path=>'nosuch'}) } qr/c +onnect:/; }

I just got this report (failed test is "lives_ok" in above snippet) and looks like target system's kernel built without UNIX socket support ("modprobe unix" probably fix this). I've no idea why anyone may need kernel compiled in this way, but question is how to avoid such FAIL reports?

Removing lives_ok test looks like ignoring/hiding issue instead of fixing it... So, is it better to remove this test, or add "skip if !AF_UNIX" somehow (and how to check this)?

Replies are listed 'Best First'.
Re: Is AF_UNIX available?
by JavaFan (Canon) on Nov 20, 2010 at 20:30 UTC
    Suggestion (no idea whether this will work): try to create an AF_UNIX socket. If it fails, check whether the error is EAFNOSUPPORT. Which ought to be the error if the address family isn't supported.
Re: Is AF_UNIX available?
by chrestomanci (Priest) on Nov 20, 2010 at 20:42 UTC

    IMHO, the only reliable cross platform way to check that AF_UNIX is available is to attempt to use it. So you could write code like:

    use English eval { # code that uses AF_UNIX }; if( $EVAL_ERROR ) { # AF_UNIX is not avalable } else { # AF_UNIX is not avalable }

    However in a test script the code that uses AF_UNIX, is a test, so in effect you are running tests where it is OK if they fail on some platforms. Tests like that are normally configured as TODO tests, so you end up with code like:

    TODO: { local $TODO = 'no UNIX sockets on Windows' if $^O =~ /Win/; use Sys::Syslog (); my $path = Sys::Syslog::_PATH_LOG() || '/dev/log'; skip 'unable to detect syslog socket', 1 if !-S $path; lives_ok { $LOG->config({type=>'unix',path=>$path}) }; throws_ok { $LOG->config({type=>'unix',path=>'nosuch'}) } qr/con +nect:/; }

    In other words, if the tests fail under windows, then it is not a problem but they are expected to pass on other platforms. I think that describes what you are trying to achieve.

    If you think marking the tests as TODO is wrong as it implies that it is something you need to fix, I would say that in this case it is a missing feature that the OS vendor needs to fix, not that they ever will.

    Couple of points with the code above. Firstly, I don't have a windows box handy, so I am assuming that nothing bad will happen if you attempt to use AF_Unix sockets on that platform. If the attempt would cause a bluescreen or suchlike, then you would obvously need to skip the tests instead.

    Secondly, there are a large number of platforms described in perlport-platforms, and I suspect that there are others besides Windows where AF_UNIX sockets are not supported, so for completeness, you should probably provide a list of values for $^O that will skip the test. Alternatively, use explain (from Test::More), to emit a message to say to users on unusual platforms that these tests might fail, and if they do should contact you with the details.

      Actually, if you check that FAIL report from my question above - it's on Linux! So, checking $^O doesn't helps here.