prove command not passing arguments after arisdottle to - perl

I'm trying to pass some parameters to a test script through the prove command. Based on some old threads where is option was hashed out, and the content's of my prove's man page (quoted below), using :: before the options should work, but prove is still parsing the test script's option as it's own:
$ prove -v t/040-unit-object-test.t :: --unit 270149
Unknown option: unit
Here the relevant part of the man page:
Arguments to Tests
It is possible to supply arguments to tests. To do so separate them
from prove's own arguments with the arisdottle, '::'. For example
prove -v t/mytest.t :: --url http://example.com
would run t/mytest.t with the options '--url http://example.com'. When
running multiple tests they will each receive the same arguments.
I tried using sudo to run the option as root, but got the same error.
I am using the Getopt::Long module to get the options, and the options work when I run the test script using plain old perl, but then my SKIP and TODO blocks don't work.
I would rather not have to use the --exec workaround.
I'm running Perl 5.10 on Mac OS 10.6.
The output of prove -V is:
prove v2.64, using Test::Harness v3.25 and Perl v5.10.0

Well, you must have two versions of prove in your $PATH, an old one from 2006 from before App::Prove existed I suggest you delete that one, and re-install App::Prove

Related

Perl executable crashes even though file is not missing

I get the following error:
Can't load '...\AppData\Local\Temp\par-6e72616f\cache-20221205133501\5743946b.xs.dll' for module GD:
load_file:
The specified module could not be found at <embedded>/DynaLoader.pm line 193.
at <embedded>/PAR/Heavy.pm line 140.
(Line breaks added for readability.)
Here is the file t2.pl:
use GD;
Here is the command to convert it to an exe (I use a batch file that timestamps it):
pp -T 20221205133501 -o t2_20221205133501.exe t2.pl
On my laptop, the exe works, but on a barebones Citrix environment it fails.
My environment:
Strawberry Perl v5.32.1 built for MSWin32-x86-multi-thread-64int
GD v2.73
I know the file is simple, but that one line is enough to cause the crash.
The file it complains about exists and is located where it is looking.
I have looked and is looks like I need to add -m GD, or -l xxx to make it work. I tried adding all the dll files I could find for GD, but failed.
I have a corporate environment so I can't really use anything that depends on external programs not in Windows 10. pp_simple depends on wxpar which I do not have. I have used:
objdump -x C:\Strawberry\perl\vendor\lib\auto\GD\GD.xs.dll | find "DLL"
which got me a list of DLLs, and I did try using them with -l.
From Re: Par with strawberry-Perl
There are likely missing DLLs that need to be added to the pp call
using the --link option.
Finding these manually can be a pain, so have a look at pp_autolink or
pp_simple (the former is mine, but adapted from the latter).
https://github.com/shawnlaffan/perl-pp-autolink
https://www.perlmonks.org/?node_id=1148802

Perl and SNMP - input options

script uses Net::SNMP module for Perl.
I'm trying to run snmpget command with some options added e.g. ( -Ir ) (here is list of options), but I haven't found any way to do that. In documentation for this module I didn't found anything about adding input options to snmp command.
If there is any other module that supports this, it would bi nice but it wouldn't be first pick as that would require a lot of changes in script (not mine script, just doing minor changes).
I could run system (or backticks) command from Perl, e.g.:
snmpget -v2c -c COMMUNITY -Ir HOST OID
and parse output but I would like to avoid that also.
Any advice or solution would be welcome since I'm still new to Perl.
Thx.
You linked to the documentation of Net::SNMP so I'm sure you've read it all before asking... Right?
There is no "command", there is only your script's calls to the API.
[Edit after the below comments]
Net::SNMP has no option to check indexes before sending the request. So, you could say the equivalent of -Ir is enabled by default. In fact, Net::SNMP does not load your MIB, so it has no way of checking the validity of your requested variables before sending the request.

How to have Dexy evaluate Perl scripts?

The dexy documentation states than any language may be used. The tutorial use the py filter to run Python file, but I didn't find any filter to run Perl file.
I try to execute a very simple Perl file
I've tried to use the bash or sh filter, but with no luck, and didn't find any execute-or-like filter.
Am I missing something obvious ?
Ok, here are the different solutions I found about this.
1. A perl filter now exist
Ok, Ana is the owner of this project and is very reactive. I asked her the question about dexy and perl on IRC, and tada ! Less than 1 hour later, there was a commit on the repository with perl support.
So, if you just get latest version and install it this way :
git clone https://github.com/dexy/dexy
cd dexy
sudo pip install -e .
You should have a perl filter.
If you want to pass arguments to a script, just use the scriptargs setting.
2. Use a bash script
Another very simple solution is to embed the launch of a perl script into a sh/bash script, and use the sh/shint/bash filter that already exist.
3. Use bash script without additional files
If you fear that the latest solution will makes you add a lot of tiny scripts in your directories, you may use the contents feature of dexy. That way, the required one-liners are defined in dexy.yaml only.
Something like :
- shell-myscript.sh|sh:
- contents: "perl ./perl/myscript.pl --any-parameter"
- perl/myscript.pl
is doing the job just fine for me.

Run pgTAP with Perl prove instead of pg_prove

I have a test-suit as usual for Perl projects, containing a lib and a t directory. The tests in t are structured through subdirectories. So I run them using:
prove -Ilib -r t/
So far nothing special, and afaik quite a standard way of testing in Perl.
Since it is the assumption, that this is the standard way of testing, I'd like to make sure that the following applies:
"If you run prove -r on t, you have tested everything that is there to test".
This is very important, since otherwise you can never be sure that you really called all the tests and the stuff is fine. Somebody calling the above would then maybe - not knowing so - just call a part of the available tests, leaving some behind. Quite annoying... tests that are not run, are of no help. It should be as easy and predictive as possible for developers to call all the tests! It is a bad thing when you have to look up how to run the rest of the test-suit. You might not know about it, or might not do it anyway.
So here comes my problem: I have to integrate some Tests using pgTAP which kindly provides the tool pg_prove. Now I have to make two commandos to do the testing. Additionally to running prove -Ilib -r I also have to run something like e.g. pg_prove -S schema=customerX -U dbuser -d dbname t/pgTAP/*.sql. The problem is not that big if you call the tests automatically from cron or what ever. But it really decreases the chance that we lazy developers run all test tests during our busy days.
So I wonder what would be the best approach to implement the tests in such a way that prove will also include those tests. Is it, that I have to create some .t-files which wrap the whole thing (and how?)? Are there any tricks I can do with the whole Harness stuff on CPAN? Would a simple test_all.sh in the root-dir, including both commandos, do the best job, even if it breaks the assumptions I made above?
So my question in short is: Can I run all tests, including pgTAP with prove? If not, is there a best practice for solving my problem?
Thanks a lot.
Yes. In fact, pg_prove just passes everything off to prove. Assuming your pgTAP tests end in .sql, you can run all your tests like this:
prove -lr --ext .sql --ext .t \
--source pgTAP \
--pgtap-option dbname=dbname \
--pgtap-option username=dbuser \
--pgtap-option suffix=.pg \
--pgtap-option set=schema=customerX
If you use Module::Build, you can also have ./Build test run all the tests, too, as I've done for circle.
See the TAP::Parser::SourceHandler::pgTAP documentation for details.

How can I find out what script, program, or shell executed my Perl script?

How would I determine what script, program, or shell executed my Perl script?
Example: I might want to have human readable output if executed from shell (customized for each type of shell), a different type of output if called as a script from another perl script, and a machine readable format if executed from a program such as a continuous integration server.
Motivation: I have a tool that changes its output based on which shell executes it. I'd normally implement this behavior as an option to the script, but this tool's design doesn't allow for options. Other shells have environment variables that indicate what shell is running. I'm working on a patch to support Powershell, which has no such special variable.
Edit: Many of these answers happen to be linux specific. Unfortuantely, Powershell is for Windows. getppid, the $ENV{SHELL} variable, and shelling out to ps won't help in this case. This script needs to run cross-platform.
You use getppid(). Take this snippet in child.pl:
my $ppid = getppid();
system("ps --no-headers $ppid");
If you run it from the command line, system will show bash or similar (among other things). Execute it with system("perl child.pl"); in another script, e.g. parent.pl, and you will see that perl parent.pl executed it.
To capture just the name of the process with arguments (thanks to ikegami for the correct ps syntax):
my $ppid = getppid();
my $ps = `ps --no-headers -o cmd $ppid`;
chomp $ps;
EDIT: An alternative to this approach, might be to create soft links to your script, make the different contexts use different links to access your script and inspect $0 to build logic around that.
I would suggest a different approach to accomplish your goal. Instead of guessing at the context, make it more explicit. Each use case is wholly separate, so have three different interfaces.
A function which can be called inside a Perl program. This would likely return a Perl data structure. This is far easier, faster and more reliable than parsing script output. It would also serve as the basis for the scripts.
A script which outputs for the current shell. It can look at $ENV{SHELL} to discover what shell is running. For bonus points, provide a switch to explicitly override.
A script which can be called inside a non-Perl program, such as your continuous integration server, and issue machine readable output. XML and/or JSON or whatever.
2 and 3 would be just thin wrappers to format the data coming out of 1.
Each is tailored to fit its specific need. Each will work without heuristics. Each will be far simpler than trying to guess the context and what the user wants.
If you can't separate 2 and 3, have the continuous integration server set an environment variable and look for it.
Depending on your environment, you may be able to pick it up from the environment variables. Consider the following code:
/usr/bin/perl -MData::Dumper -e 'print Dumper(\%ENV);' | grep sh
On my Ubuntu system, it gets me:
'SHELL' => '/bin/bash',
So I guess that says I'm running perl from a bash shell. If you use something else, the SHELL variable may give you a hint.
But let's say you know you're in bash, but perl is run from a subshell. Then try:
/bin/sh -c "/usr/bin/perl -MData::Dumper -e 'print Dumper(\%ENV);'" | grep sh
You will find:
'_' => '/bin/sh',
'SHELL' => '/bin/bash',
So the shell is still bash, but bash has a variable $_ which also show the absolute filename of the shell or script being executed, which may also give a valuable hint. Similarily, for other environments there will most probably be clues left in the perl %ENV hash that should give you valuable hints.
If you're running PowerShell 2.0 or above (most likely), you can infer the shell as a parent process by examining the environment variable %psmodulepath%. By default, it points to the system modules under %windir%\system32\windowspowershell\v1.0\modules; this is what you would see if you examine the variable from cmd.exe.
However, when PowerShell starts up, it prepends the user's default module search path to this environment variable which looks like: %userprofile%\documents\windowspowershell\modules. This is inherited by child processes. So, your logic would be to test if %psmodulepath% starts with %userprofile% to detect powershell 2.0 or higher. This won't work in PowerShell 1.0 because it does not support modules.
This is on Windows XP with PowerShell v2.0, so take it with a grain of salt.
In a cmd.exe shell, I get:
PSModulePath=C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\
whereas in the PowerShell console window, I get:
PSModulePath=E:\Home\user\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsP
owerShell\v1.0\Modules\
where E:\Home\user is where my "My Documents" folder is. So, one heuristic may be to check if PSModulePath contains a user dependent path.
In addition, in a console window, I get:
!::=::\
in the environment. From the PowerShell ISE, I get:
!::=::\
!C:=C:\Documents and Settings\user