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

For my Raspberry Pi build/test automation regimen, there are two aspects of code that require root permissions, as they will not work with /dev/gpiomem (fwiw, one aspect is Pulse-Width Modulation functionality, the other deals with the Pi's hardware clock registers).

I obviously don't want to have the actual code up and randomly sudo, instead, a note in the docs will specify if these features are used, you'll need to setuid or run your script with sudo.

Likewise, I don't want to run the whole test suite with root, just two files.

I'm thinking something like the following which appears to work well:

use warnings; use strict; use Test::More; if ($> != 0){ system('sudo', 'prove', '-l', $0); exit; } is 1, 1, "ok"; done_testing();

Is this reasonable, or am I overlooking an easier or better way to do this?

Replies are listed 'Best First'.
Re: Running specific test files with sudo
by Corion (Patriarch) on Mar 19, 2017 at 16:28 UTC

    Why rerun your test through prove instead of simply rerunning your test program? That way, whatever harness the user uses will just receive the output from your restarted program...

    Also, there is a skip command in Test::More, which is a bit cumbersome to use but outputs a nicer message than a passing test:

    use Test::More; plan tests => 10; if( $> != 0 ) { # re-exec as root: # hope we didn't have -Ilib or -Mblib on the invocation line exec 'sudo', $0, @ARGV; # Also see Devel::PL_origargv }; if( $> != 0 ) { SKIP: { skip "Must be root", 10; }; exit; }; ... run tests as root ...

      Thanks Corion.

      I do already use the skip feature of Test::More in certain cases. Below is an example so that if a user isn't on a Pi, certain test files will skip. This prevents needless test failures on the CPAN:

      if (! $ENV{PI_BOARD}){ plan skip_all => "not on a pi board (PI_BOARD env var not set)\n"; }

      I will give using exec a go.

Re: Running specific test files with sudo
by haukex (Archbishop) on Mar 19, 2017 at 18:18 UTC
    there are two aspects of code that require root permissions, as they will not work with /dev/gpiomem

    There should be a way to give users access without requiring root. For example, on one of my RPis, there are udev rules in /etc/udev/rules.d/99-com.rules that put /dev/gpiomem into the gpio group, and my pi user is already in that group. I've also added a few custom rules for other devices, all it takes is adding the GROUP="foo" command to the corresponding udev rule.

      Cheers, haukex.

      Problem is with these two pieces of functionality (PWM and direct mods to the hardware clock), that doesn't work, as they can't use /dev/gpiomem, as they aren't directly related to the GPIO itself, and function outside of that scope.

      I'm still looking for some form of workaround. All other functionality thus far works fine the way you state, as I'm just dealing with GPIO directly.

      update: That said, if you happen to come across any C/Python/<insert lang> code that operates on either of these (PWM is *far* more common) without requiring root access, I would hugely appreciate a reply or private message, so that I can review the code and see how they are doing it. I know some libraries (particularly Python) that secretly use sudo, but nothing (ie. docs/changelog, CLI notice etc) mentions this. I outright refuse to do this, as it opens potential security holes and isn't fair to the end-user. I'd sooner have the Pi crash hard, then, when I get emails, I can say "RTFM for X and Y again" ;) (well not really, but if sudo is secretly used in one place, who knows where else it is used).

      I did have some of my code doing this in the extreme early stages of this project, but it felt dirty and I backed it all out. This was at the time that /dev/gpiomem wasn't standard, and *all* code paths to the GPIO required root.

      Now that those restrictions have been lifted/integrated into the OS by default (newer Raspbian OS cuts), there's no need for this less specific non-GPIO-direct functionality.