wxPerl and PAR::Packer and missing dependencies - perl

My application is made with wxPerl, and I make an executable with PAR::Packer. It works fine on my machines (macOS and Windows), but not on a machine without a Perl/wxPerl installation; in fact, it doesn't work on my machines either if I change the name of the directory which holds the Perl installation, e.g. to perl5X or StrawberryX, before running the executable.
On macOS I can get error messages from the terminal:
Can't load '/var/folders/[...]/ca54e36a.bundle' for module Wx:
dlopen(/var/folders/[...]/ca54e36a.bundle,
1): Library not loaded: /[...]/Alien/wxWidgets/osx_cocoa_3_0_2_uni/lib/libwx_osx_cocoau_core-3.0.0.2.0.dylib
Referenced from: /var/folders/[...]/libwx_osx_cocoau_adv-3.0.dylib
Reason: image not found at <embedded>/DynaLoader.pm line 197.
at <embedded>/PAR/Heavy.pm line 140.
I have tried to --link all the .dylib/.dll files (errors about other files occur too), but the same error occurs.
I have use Wx::Perl::Packager in my source file as explained here, and run pp (or, on Windows, wxpar; on macOS that doesn't work) like:
pp -x -c -o MyApp.exe script/app.pl -a assets/collections
The data files included with -a gets unpacked into the right place when the executable is run, so it works that far. But then it stops.
So, what am I missing?
-- EDIT 1
Edited for clarity.
-- EDIT 2
I include a Minimal (not) Working Example:
use warnings;
use strict;
package MyFrame;
use Wx::Perl::Packager;
use Wx;
use base 'Wx::Frame';
sub new {
my $class = shift;
my $self
= $class->SUPER::new( undef, -1, 'Test', [ -1, -1 ], [ 250, 150 ], );
return $self;
}
1;
package MyApp;
use base 'Wx::App';
sub OnInit {
my ($self) = #_;
my $frame = MyFrame->new();
$frame->Show();
}
1;
package main;
MyApp->new->MainLoop;
I then run pp like this:
#!/bin/bash
pp -x -c -o minimal.app \
-l /Users/Patrik/perl5/perlbrew/perls/perl-5.30.0/lib/site_perl/5.30.0/darwin-2level/Alien/wxWidgets/osx_cocoa_3_0_2_uni/lib/libwx_osx_cocoau_core-3.0.0.2.0.dylib \
minimal.pl
But after "hiding" the Perl installation and running the app I get
...
Library not loaded: /Users/Patrik/perl5/perlbrew/perls/perl-5.30.0/lib/site_perl/5.30.0/darwin-2level/Alien/wxWidgets/osx_cocoa_3_0_2_uni/lib/libwx_osx_cocoau_core-3.0.0.2.0.dylib
...

Related

Perl and Selenium::Remote::Driver

EDITED AGAIN
I have a server on AWS somewhere in Northern Virginia and this is my monitoring server. I ssh into this Ubuntu server from another State to do system administration. I want to do web automation tests on this server which will test a web application on the Internet hitting a URL and verify that I can selenium test a login and authenticate successfully. This server is on an AWS cloud I'm not quite sure which Perl module to use since I'm accessing it remotely.
There are two CPAN modules: Selenium::Remote::Driver and WWW::Selenium. I have tried both and they are giving me issues. And I really don't know which is appropriate for my scenario. When I use Selenium::Remote::Driver, I get the following error:
Selenium server did not return proper status at /usr/local/share/perl/5.18.2/Selenium/Remote/Driver.pm line 401.
When I use WWW::Selenium, I get this error:
Failed to start new browser session: org.openqa.selenium.server.RemoteCommandException: Error while launching browser
I was able to launch firefox manually from the AWS monitoring server by exporting the DISPLAY but it was really slow. I have heard that I can use a headless browser but I would have to export the DISPLAY by:
export DISPLAY=:5
But remember, I'm sshing into this AWS/Selenium server from my desktop so I'm assuming I use the above command on the AWS/Selenium Server while I'm ssh into it from my desktop? Actually, at this point, I'm not sure I'm doing here. Can somebody help?
The problem in this type of questions is that the variety of configurations and binaries in your setup might be so broad that the it is hard to actually provide a straight and correct answer for YOUR SETUP.
This answer has the following assumptions:
you have downloaded the selenium-server-standalone.jar into /usr/lib/
you have jdk 1.8 ( run the java -version in the shell
you have installed and configured the xvfb-run ( it is a fight on it's own )
So :
```
# ssh to your server , obs the -X !
ssh -X user-name#server-name
# start the selenium-server-standalone on the server
xvfb-run -e /dev/stdout java -Dwebdriver.chrome.driver=/usr/bin/chromedriver -jar /usr/lib/selenium-server-standalone.jar &
# one liner test - this is one veery long one
perl -e 'use strict ; use warnings ; use Data::Printer ; my $host="127.0.0.1"; use Selenium::Remote::Driver;my $driver = Selenium::Remote::Driver->new( "browser_name" =>"chrome", "error_handler" => sub { print $_[1]; croak 'goodbye'; }, "remote_server_addr" => "$host","port"=> "4444");$driver->debug_on();$driver->get("http://www.google.com"); print $driver->get_title();$driver->quit();' &
```
Here is the code in the one-liner as a perl script
#!/usr/bin/env perl
use strict ;
use warnings ;
use Carp ;
use Data::Printer ;
use Selenium::Remote::Driver;
my $host="127.0.0.1";
my $driver = Selenium::Remote::Driver->new(
"browser_name" =>"chrome"
, "error_handler" => sub { print $_[1]; croak 'goodbye' ; }
, "remote_server_addr" => "$host"
, "port"=> "4444") ;
$driver->debug_on() ;
$driver->get("http://www.google.com");
print $driver->get_title();
$driver->quit();
The output should look something like:
```
Prepping get
Executing get
REQ: POST, http://127.0.0.1:4444/wd/hub/session/ddb9c2575ab026cdb8c640bdc554181b/url, {"url":"http://www.google.com"}
RES: {"sessionId":"ddb9c2575ab026cdb8c640bdc554181b","status":0,"value":null}
Prepping getTitle
Executing getTitle
REQ: GET, http://127.0.0.1:4444/wd/hub/session/ddb9c2575ab026cdb8c640bdc554181b/title, {}
RES: {"sessionId":"ddb9c2575ab026cdb8c640bdc554181b","status":0,"value":"Google"}
GooglePrepping quit
Executing quit
REQ: DELETE, http://127.0.0.1:4444/wd/hub/session/ddb9c2575ab026cdb8c640bdc554181b, {}
RES: {"sessionId":"ddb9c2575ab026cdb8c640bdc554181b","status":0,"value":null}
```
Try running the below code:
#!/usr/bin/perl
use warnings;
use strict;
use Selenium::Remote::Driver;
my $host = "10.10.1.1"; //Enter your server IP in this place
my $driver = new Selenium::Remote::Driver('remote_server_addr' => $host,
'port' => '4444',
'auto_close' => 0);
$driver->get('http://www.google.com');

Installing cpan Modules in cygwin fails

I am trying to install different Perl Modules from CPAN in a cygwin-32bit enviroment and always get Errors of the same kind. This one is from trying to install Net::SSLeay, did make, install and tried force install too, nothing seemed to work.
drmariad#drmariad-MOBL ~/.cpan/build/Net-SSLeay-1.70-eDSzRW$ make install
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
chmod 755 /usr/lib/perl5/site_perl/5.14/i686-cygwin-threads-64int/auto//Net/SSLeay/SSLeay.dll
/bin/find /usr/lib/perl5/site_perl/5.14/i686-cygwin-threads-64int/auto/ -xdev -name \*.dll /bin/rebase -sOT -
/bin/find: paths must precede expression: /bin/rebase
Usage: /bin/find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
Makefile:731: recipe for target 'pure_install' failed
make: *** [pure_install] Error 1
Most of the time it is the bin/find fails message i get in the installations, but i don't know how to change that behaviour. I got errors and failures with most of the modules i tryed to install.
My update-to-date Cygwin comes with
ExtUtils::MakeMaker 6.57_05
ExtUtils::MM_Cygwin 6.57_07
That's odd for a few reason, but what we care about is that version of MM_Cygwin is buggy.
sub install {
my($self, %attribs) = #_;
my $s = ExtUtils::MM_Unix::install($self, %attribs);
return '' unless $s;
return $s unless %{$self->{XS}};
my $INSTALLDIRS = $self->{INSTALLDIRS};
my $INSTALLLIB = $self->{"INSTALL". ($INSTALLDIRS eq 'perl' ? 'ARCHLIB' : uc($INSTALLDIRS)."ARCH")};
my $dop = "\$\(DESTDIR\)$INSTALLLIB/auto/";
my $dll = "$dop/$self->{FULLEXT}/$self->{BASEEXT}.$self->{DLEXT}";
$s =~ s|^(pure_install :: pure_\$\(INSTALLDIRS\)_install\n\t)\$\(NOECHO\) \$\(NOOP\)\n|$1\$(CHMOD) \$(PERM_RWX) $dll\n\t/bin/find $dop -xdev -name \\*.$self->{DLEXT} /bin/rebase -sOT -\n|m if (( $Config{myarchname} eq 'i686-cygwin') and not ( exists $ENV{CYGPORT_PACKAGE_VERSION} ));
$s;
}
You could add the missing | to /usr/lib/perl5/5.14/ExtUtils/MM_Cygwin.pm as a quick permanent fix.
Alternatively, Cygwin has a package named perl-ExtUtils-MakeMaker that upgrade the distribution to 7.04_01.
...Except the bug is still present there. If you have this package installed, the file to fix is /usr/lib/perl5/vendor_perl/5.14/ExtUtils/MM_Cygwin.pm.
Alternatively, you can upgrade ExtUtils::MakeMaker to the latest dev release (which uses a completely different command).
cpan B/BI/BINGOS/ExtUtils-MakeMaker-7.05_22.tar.gz

Mojolicious + MongoDB: Can't locate MongoDB.pm error

My app crashes each time it includes as much as "use MongoDB;" in my perl app file.
I have installed MongoDB successfully. I can check my databases use one or the other, check for collections, create new collections, all from the shell.
If I try to connect to mongoDb from mojolicious app like:
!/usr/bin/env perl
use Mojolicious::Lite;
use MongoDB;
use MongoDB::OID;
my $mongo_port = shift || 27017;
helper 'mongo' => sub {
my ($self, $name) = #_;
my $host = 'localhost:' . $mongo_port;
my $conn = MongoDB::MongoClient->new(host => $host);
my $db = $conn->get_database('test');
};
helper 'value2oid' => sub {
my ($self, $value) = #_;
MongoDB::OID->new($value);
};
If I have a working app and include as much as :
Use MongoDB;
I get:
Can't load application from file "/Users/eevitomperi/Desktop/Programming/Perl/mojoliciousApp/foodAbout/app.pl": Can't locate MongoDB.pm in #INC (you may need to install the MongoDB module) (#INC contains: /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2/darwin-thread-multi-2level /Library/Perl/Updates/5.18.2 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at /Users/eevitomperi/Desktop/Programming/Perl/mojoliciousApp/foodAbout/app.pl line 4.
BEGIN failed--compilation aborted at /Users/eevitomperi/Desktop/Programming/Perl/mojoliciousApp/foodAbout/app.pl line 4.
I am completely new to mongo, mojolicious and perl so I guess I did not install some package?
Does the MongoDB files(mongo, mongod....) have to be within the mojolicious project ?
Not sure what I am missing and all documentation starts with the use of "Use MongoDB;" within mojolicious app so not sure what to do.
Hopefully someone can point out what I missed.
Install module:
cpanm Mojolicious::Plugin::Mongodb
Fix the following:
Can't write to /Library/Perl/5.18 and /usr/local/bin: Installing modules to /Users/eevitomperi/perl5
! To turn off this warning, you have to do one of the following:
! - run me as a root or with --sudo option (to install to /Library/Perl/5.18 and /usr/local/bin)
! - Configure local::lib your existing local::lib in this shell to set PERL_MM_OPT etc.
! - Install local::lib by running the following commands
By running:
cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
Now I can connect to Mongo from mojolicious

Why does Perl's Net::SFTP->new complain about "Not an ARRAY reference"?

I am trying to use Net::SFTP to get connected to remote server.
My script is:
my %args = (
ssh_args => {
user => 'canneu_scp',
identity_files => [ '/home/home1/cgrshah/responsys/capgemini.private' ],
debug => 1,
} );
my $targetserver='files.responsys.net';
my $sftp = Net::SFTP->new($targetserver, %args)
or die "could not open connection to $targetserver\n";
But when I run this, I get an error stating:
Not an ARRAY reference at /usr/lib/perl5/site_perl/5.8.1/Net/SFTP.pm line 36.
Can anyone help me with this?
This is just a wild shot in the dark, but the user option should not be in the hash handed to ssh_args, it is at the same level. Try using this code instead:
my $sftp = Net::SFTP->new(
$targetserver,
user => 'canneu_scp',
ssh_args => {
identity_files => [ '/home/home1/cgrshah/responsys/capgemini.private' ],
debug => 1,
}
) or die "could not open connection to $targetserver\n";
It sounds like the code above got you further along, and now you are having problems because your version of Math::BigInt is too old. I see three ways to move forward:
switch to an RSA key instead of a DSA key
find an RPM of Math::BigInt version 1.78 or later
manually install a copy of Math::BigInt
The third option has many pitfalls, and if you decide to go with it I would suggest the following steps:
install App::cpanminus
make sure you have a gcc installed
run wget -O- http://cpanmin.us | perl - --local-lib=~/perl5 App::cpanminus
add ~/perl5/bin to your path
install Math::BigInt into your home directory with cpanm --local-lib=~/perl5 Math::BigInt
add use lib "$ENV{HOME}/perl5"; to the start of your script so it can find the new modules

Why does my Perl unit test fail in EPIC but work in the debugger?

Has anyone ever experienced a unit test that fails and when they tried to debug it to find out where the failure was occurring, the unit test succeeds when running the code in the debugger?
I'm using Eclipse 3.5.1 with EPIC 0.6.35 and ActiveState ActivePerl 5.10.0. I wrote module A and module B both with multiple routines. A routine in module B calls a bunch of routines from module A. I'm adding mock objects to my module B unit test file to try to get more complete code coverage on module B where the code in module B tests to see if all the calls to module As routines fail or succeed. So I added some mock objects to my unit test to force some of the module A routines to return failures, but I was not getting the failures as expected. When I debugged my unit test file, the calls to the module A routine did fail as expected (and my unit test succeeds). When I run the unit test file as normal without debugging, the call to the mocked Module A routine does not fail as expected (and my unit test fails).
What could be going on here? I'll try to post a working example of my problem if I can get it to fail using a small set of simple code.
ADDENDUM: I got my code whittled down to a bare minimum set that demonstrates my problem. Details and a working example of the problem follows:
My Eclipse project contains a "lib" directory with two modules ... MainModule.pm and UtilityModule.pm. My Eclipse project also contains at the top level a unit test file named MainModuleTest.t and a text file called input_file.txt which just contains some garbage text.
EclipseProject/
MainModuleTest.t
input_file.txt
lib/
MainModule.pm
UtilityModule.pm
Contents of the MainModuleTest.t file:
use Test::More qw(no_plan);
use Test::MockModule;
use MainModule qw( mainModuleRoutine );
$testName = "force the Utility Module call to fail";
# set up mock utility routine that fails
my $mocked = new Test::MockModule('UtilityModule');
$mocked->mock( 'slurpFile', undef );
# call the routine under test
my $return_value = mainModuleRoutine( 'input_file.txt' );
if ( defined($return_value) ) {
# failure; actually expected undefined return value
fail($testName);
}
else {
# this is what we expect to occur
pass($testName);
}
Contents of the MainModule.pm file:
package MainModule;
use strict;
use warnings;
use Exporter;
use base qw(Exporter);
use UtilityModule qw( slurpFile );
our #EXPORT_OK = qw( mainModuleRoutine );
sub mainModuleRoutine {
my ( $file_name ) = #_;
my $file_contents = slurpFile($file_name);
if( !defined($file_contents) ) {
# failure
print STDERR "slurpFile() encountered a problem!\n";
return;
}
print "slurpFile() was successful!\n";
return $file_contents;
}
1;
Contents of the UtilityModule.pm file:
package UtilityModule;
use strict;
use warnings;
use Exporter;
use base qw(Exporter);
our #EXPORT_OK = qw( slurpFile );
sub slurpFile {
my ( $file_name ) = #_;
my $filehandle;
my $file_contents = "";
if ( open( $filehandle, '<', $file_name ) ) {
local $/=undef;
$file_contents = <$filehandle>;
local $/='\n';
close( $filehandle );
}
else {
print STDERR "Unable to open $file_name for read: $!";
return;
}
return $file_contents;
}
1;
When I right-click on MainModuleTest.t in Eclipse and select Run As | Perl Local, it gives me the following output:
slurpFile() was successful!
not ok 1 - force the Utility Module call to fail
1..1
# Failed test 'force the Utility Module call to fail'
# at D:/Documents and Settings/[SNIP]/MainModuleTest.t line 13.
# Looks like you failed 1 test of 1.
When I right click on the same unit test file and select Debug As | Perl Local, it gives me the following output:
slurpFile() encountered a problem!
ok 1 - force the Utility Module call to fail
1..1
So, this is obviously a problem. Run As and Debug As should give the same results, right?!?!?
Both Exporter and Test::MockModule work by manipulating the symbol table. Things that do that don't always play nicely together. In this case, Test::MockModule is installing the mocked version of slurpFile into UtilityModule after Exporter has already exported it to MainModule. The alias that MainModule is using still points to the original version.
To fix it, change MainModule to use the fully qualified subroutine name:
my $file_contents = UtilityModule::slurpFile($file_name);
The reason this works in the debugger is that the debugger also uses symbol table manipulation to install hooks. Those hooks must be getting installed in the right way and at the right time to avoid the mismatch that occurs normally.
It's arguable that it's a bug (in the debugger) any time the code behaves differently there than it does when run outside the debugger, but when you have three modules all mucking with the symbol table it's not surprising that things might behave oddly.
Does your mocking manipulate the symbol table? I've seen a bug in the debugger that interferes with symbol table munging. Although in my case the problem was reversed; the code broke under the debugger but worked when run normally.