1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
|
#! /usr/bin/perl
#
# TestTarget_LVRT - how to manage the test environment on a LabVIEW RT target.
#
# We can FTP files to and from the LabVIEW target, but there's no NFS or
# SMB shares.
# Most information about the target itself is specified via environment
# variables. Environment variables with settings are named using the target's
# config name with a specific suffix. The current environment variables are:
# <config-name>_IPNAME - the host name/IP of the target.
# <config-name>_CTLPORT- the TCP port number to connect to for the test
# controller. If this is not set, port 8888 is used.
# <config-name>_FSROOT - the root of the filesystem on the target where
# ACE files will be created from (cwd, if you will).
# If this is not set, "\ni-rt" is used as the root.
#
# Each of these settings are stored in a member variable of the same name in
# each object. The process objects can access them using, e.g.,
# $self->{TARGET}->{IPNAME}.
#
# This class also makes an FTP object available to process objects that are
# created. FTP is set up before creating a process object and can be used to
# transfer files to and from the LVRT target.
package PerlACE::TestTarget_LVRT;
our @ISA = "PerlACE::TestTarget";
### Constructor and Destructor
sub new
{
my $proto = shift;
my $config_name = shift;
my $class = ref ($proto) || $proto;
my $self = {};
bless ($self, $class);
$self->GetConfigSettings($config_name);
my $targethost;
my $env_name = $config_name.'_IPNAME';
if (exists $ENV{$env_name}) {
$targethost = $ENV{$env_name};
}
else {
print STDERR "You must define target hostname/IP with $env_name\n";
undef $self;
return undef;
}
$env_name = $config_name.'_CTLPORT';
if (exists $ENV{$env_name}) {
$self->{CTLPORT} = $ENV{$env_name};
}
else {
print STDERR "Warning: no $env_name variable; falling back to ",
"port 8888\n";
$self->{CTLPORT} = 8888;
}
$env_name = $config_name.'_FSROOT';
my $fsroot = '\\ni-rt\\system';
if (exists $ENV{$env_name}) {
$fsroot = $ENV{$env_name};
}
else {
print STDERR "Warning: no $env_name variable; falling back ",
"to $fsroot\n";
}
$self->{FSROOT} = $fsroot;
$self->{REBOOT_CMD} = $ENV{'ACE_REBOOT_LVRT_CMD'};
if (!defined $self->{REBOOT_CMD}) {
$self->{REBOOT_CMD} = 'I_Need_A_Reboot_Command';
}
$self->{REBOOT_TIME} = $ENV{'ACE_LVRT_REBOOT_TIME'};
if (!defined $self->{REBOOT_TIME}) {
$self->{REBOOT_TIME} = 200;
}
$self->{REBOOT_TIME} = $ENV{'ACE_RUN_LVRT_REBOOT_TIME'};
if (!defined $self->{REBOOT_TIME}) {
$self->{REBOOT_TIME} = 200;
}
$self->{REBOOT_NEEDED} = undef;
$self->{FTP} = new Net::FTP ($targethost);
$self->{IPNAME} = $targethost;
if (!defined $self->{FTP}) {
print STDERR "Error opening FTP to $targethost: $@\n";
$self->{REBOOT_NEEDED} = 1;
undef $self;
return undef;
}
$self->{FTP}->login("","");
return $self;
}
sub DESTROY
{
my $self = shift;
# Reboot if needed; set up clean for the next test.
if (defined $self->{REBOOT_NEEDED} && $self->{REBOOT_CMD}) {
$self->RebootNow;
}
# See if there's a log; should be able to retrieve it from rebooted target.
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
print STDERR "LVRT target checking for remaining log...\n";
}
$self->GetStderrLog();
if (defined $self->{FTP}) {
$self->{FTP}->close;
$self->{FTP} = undef;
}
}
##################################################################
sub LocalFile ($)
{
my $self = shift;
my $file = shift;
my $newfile = $self->{FSROOT} . '\\' . $file;
print STDERR "LVRT LocalFile for $file is $newfile\n";
return $newfile;
}
sub DeleteFile ($)
{
my $self = shift;
$self->{FTP}->login("","");
foreach my $file (@_) {
my $newfile = $self->LocalFile($file);
$self->{FTP}->delete($newfile);
}
}
sub GetFile ($)
{
# Use FTP to retrieve the file from the target; should still be open.
# If only one name is given, use it for both local and remote (after
# properly LocalFile-ing it). If both names are given, assume the caller
# knows what he wants and don't adjust the paths.
my $self = shift;
my $remote_file = shift;
my $local_file = shift;
if (!defined $local_file) {
$local_file = $remote_file;
$remote_file = $self->LocalFile($local_file);
}
$self->{FTP}->ascii();
if ($self->{FTP}->get($remote_file, $local_file)) {
return 0;
}
return -1;
}
sub WaitForFileTimed ($)
{
my $self = shift;
my $file = shift;
my $timeout = shift;
my $newfile = $self->LocalFile($file);
my $targetport = $self->{CTLPORT};
my $target = new Net::Telnet(Errmode => 'return');
if (!$target->open(Host => $self->{IPNAME}, Port => $targetport)) {
print STDERR "ERROR: target $self->{IPNAME}:$targetport: ",
$target->errmsg(), "\n";
return -1;
}
my $cmdline = "waitforfile $newfile $timeout";
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
print "-> $cmdline\n";
}
$target->print("$cmdline");
my $reply;
# Add a small comms delay factor to the timeout
$timeout = $timeout + 2;
$reply = $target->getline(Timeout => $timeout);
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
print "<- $reply\n";
}
$target->close();
if ($reply eq "OK\n") {
return 0;
}
return -1;
}
sub CreateProcess ($)
{
my $self = shift;
my $process = new PerlACE::ProcessLVRT ($self, @_);
return $process;
}
sub GetStderrLog ($)
{
my $self = shift;
# Tell the target to snapshot the stderr log; if there is one, copy
# it up here and put it out to our stderr.
my $targetport = $self->{CTLPORT};
my $target = new Net::Telnet(Errmode => 'return');
if (!$target->open(Host => $self->{IPNAME}, Port => $targetport)) {
print STDERR "ERROR: target $self->{IPNAME}:$targetport: ",
$target->errmsg(), "\n";
return;
}
my $cmdline = "snaplog";
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
print "-> $cmdline\n";
}
$target->print("$cmdline");
my $reply;
$reply = $target->getline();
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
print "<- $reply\n";
}
$target->close();
if ($reply eq "NONE\n") {
return;
}
chomp $reply;
if (undef $self->{FTP}) {
$self->{FTP} = new Net::FTP ($self->{IPNAME});
if (!defined $self->{FTP}) {
print STDERR "$@\n";
return -1;
}
$self->{FTP}->login("","");
}
$self->{FTP}->ascii();
if ($self->{FTP}->get($reply, "stderr.txt")) {
$self->{FTP}->delete($reply);
open(LOG, "stderr.txt");
while (<LOG>) {
print STDERR;
}
close LOG;
unlink "stderr.txt";
}
return;
}
# Copy a file to the target. Adjust for different types (DLL, EXE, TEXT)
# and debug/non (for DLLs). Additionally, a file can be removed when this
# object is deleted, or left in place.
sub NeedFile ($)
{
my $self = shift;
}
# Need a reboot when this target is destroyed.
sub NeedReboot ($)
{
my $self = shift;
$self->{REBOOT_NEEDED} = 1;
}
# Reboot target
sub RebootNow ($)
{
my $self = shift;
$self->{REBOOT_NEEDED} = undef;
print STDERR "Attempting to reboot target...\n";
if (defined $self->{FTP}) {
$self->{FTP}->close;
$self->{FTP} = undef;
}
system ($self->{REBOOT_CMD});
sleep ($self->{REBOOT_TIME});
}
# Reboot now then try to restore the FTP connection.
sub RebootReset ($)
{
my $self = shift;
$self->RebootNow;
my $targethost = $self->{IPNAME};
$self->{FTP} = new Net::FTP ($targethost);
if (!defined $self->{FTP}) {
print STDERR "Error reestablishing FTP to $targethost: $@\n";
}
else {
$self->{FTP}->login("","");
}
}
sub KillAll ($)
{
my $self = shift;
my $procmask = shift;
PerlACE::ProcessLVRT::kill_all ($procmask, $self);
}
1;
|