3 # ProcessLVRT - how to run ACE+TAO tests on a LabVIEW RT target.
4 # Tests on LabVIEW RT are not executables - LabVIEW RT can't start plain
5 # executables; the tests are built/packaged as DLLs and loaded and executed
6 # from a DLL loaded at LabVIEW RT boot time. The DLL on the target listens
7 # on a TCP port (8888 by default) for connections from the host. Host requests
8 # actions using text commands to the target.
10 # NOTE: This module requires the Net-Telnet Perl module.
12 # We can FTP files to and from the LabVIEW target, but there's no NFS or
15 package PerlACE
::ProcessLVRT
;
16 our @ISA = "PerlACE::Process";
24 use POSIX
qw(:time_h);
26 $PerlACE::ProcessLVRT
::ExeSubDir
= './';
28 ### Check for -ExeSubDir commands, store the last one
31 for(my $i = 0; $i <= $#ARGV; ++$i) {
32 if ($ARGV[$i] eq '-ExeSubDir') {
33 if (defined $ARGV[$i + 1]) {
34 $PerlACE::ProcessLVRT
::ExeSubDir
= $ARGV[++$i].'/';
37 print STDERR
"You must pass a directory with ExeSubDir\n";
42 push @new_argv, $ARGV[$i];
47 ### Constructor and Destructor
52 my $class = ref ($proto) || $proto;
55 $self->{TARGET
} = shift;
56 $self->{EXECUTABLE
} = shift;
57 $self->{ARGUMENTS
} = shift;
59 $self->{IGNOREEXESUBDIR
} = 1;
61 bless ($self, $class);
69 if ($self->{RUNNING
} == 1) {
70 print STDERR
"ERROR: <", $self->{EXECUTABLE
},
71 "> still running upon object destruction\n";
74 if (defined $self->{TELNET
}) {
75 $self->{TELNET
}->close();
76 $self->{TELNET
} = undef;
80 ###############################################################################
82 # Adjust executable name for LabVIEW RT testing needs. These tests are DLLs.
89 $self->{EXECUTABLE
} = shift;
92 my $executable = $self->{EXECUTABLE
};
94 my $basename = basename
($executable);
95 my $dirname = dirname
($executable). '/';
96 my $subdir = $PerlACE::ProcessLVRT
::ExeSubDir
;
97 if (defined $self->{TARGET
}) {
98 $subdir = $self->{TARGET
}->ExeSubDir();
100 $executable = $dirname.$subdir.$basename.".DLL";
101 $executable =~ s/\//\\/g; # / <- # color coding issue in devenv
111 $self->{ARGUMENTS
} = shift;
114 return $self->{ARGUMENTS
};
121 my $commandline = "run " . basename
($self->Executable(), ".dll");
122 if (defined $self->{ARGUMENTS
}) {
123 $commandline .= ' '.$self->{ARGUMENTS
};
129 ###############################################################################
131 # Spawn the process and continue.
137 if ($self->{RUNNING
} == 1) {
138 print STDERR
"ERROR: Cannot Spawn: <", $self->Executable (),
139 "> already running\n";
143 if (!defined $self->{EXECUTABLE
}) {
144 print STDERR
"ERROR: Cannot Spawn: No executable specified\n";
148 if ($self->{IGNOREEXESUBDIR
} == 0) {
149 if (!-f
$self->Executable ()) {
150 print STDERR
"ERROR: Cannot Spawn: <", $self->Executable (),
158 my $program = $self->Executable ();
159 my $cwdrel = dirname
($program);
160 my $target_ace_root = $self->{TARGET
}->ACE_ROOT();
161 if (length ($cwdrel) > 0) {
162 $cwdrel = File
::Spec
->abs2rel(cwd
(), $target_ace_root);
165 $cwdrel = File
::Spec
->abs2rel($cwdrel, $target_ace_root);
168 $self->{TARGET
}->{FTP
}->cwd($self->{TARGET
}->{FSROOT
});
169 $self->{TARGET
}->{FTP
}->binary();
170 $self->{TARGET
}->{FTP
}->put($program);
172 my $targethost = $self->{TARGET
}->{IPNAME
};
173 my $targetport = $self->{TARGET
}->{CTLPORT
};
174 $self->{TELNET
} = new Net
::Telnet
(Errmode
=> 'return');
175 if (!$self->{TELNET
}->open(Host
=> $targethost, Port
=> $targetport)) {
176 print STDERR
"ERROR: target $targethost:$targetport: ",
177 $self->{TELNET
}->errmsg(), "\n";
178 $self->{TELNET
} = undef;
179 $self->{TARGET
}->NeedReboot;
180 $self->{TARGET
}->{FTP
}->delete($program);
183 my $cmdline = $self->CommandLine();
184 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
185 print "-> $cmdline\n";
187 $self->{TELNET
}->print("$cmdline");
189 $reply = $self->{TELNET
}->getline();
190 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
193 if ($reply eq "OK\n") {
194 $self->{RUNNING
} = 1;
197 print STDERR
"ERROR: can't $cmdline: " . $reply . "\n";
198 $self->{TARGET
}->{FTP
}->delete($program);
199 # Not unless can't get the response. $self->{TARGET}->NeedReboot;
204 # Wait for the process to exit or kill after a time period
211 my $status = $self->TimedWait ($timeout);
213 $self->{RUNNING
} = 0;
215 # If the test timed out, the target is probably toast. Don't bother
216 # trying to get the log file until after rebooting and resetting FTP.
218 print STDERR
"ERROR: $self->{EXECUTABLE} timedout\n";
222 # Now get the log file from the test, and delete the test from
223 # the target. The FTP session should still be open.
224 my $program = $self->Executable ();
225 my $logname = basename
($program,".dll") . ".log";
226 my $target_log_path = $self->{TARGET
}->{FSROOT
} . "\\log\\" . $logname;
227 $program = basename
($program);
228 $self->{TARGET
}->{FTP
}->delete($program);
229 $self->{TARGET
}->{FTP
}->get($target_log_path,"log\\$logname");
230 $self->{TARGET
}->{FTP
}->delete($target_log_path);
236 # Do a Spawn and immediately WaitKill
238 sub SpawnWaitKill
($)
242 my $status = $self->Spawn ();
244 $status = $self->WaitKill ($timeout);
250 sub TerminateWaitKill
($)
255 if ($self->{RUNNING
}) {
256 print STDERR
"INFO: $self->{EXECUTABLE} being killed.\n";
260 return $self->WaitKill ($timeout);
267 if ($self->{RUNNING
}) {
268 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
271 $self->{TELNET
}->print("kill");
272 # Just wait for any reply; don't care what it is.
273 my $reply = $self->{TELNET
}->getline();
274 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
279 $self->{RUNNING
} = 0;
280 # Trying to kill a LabVIEW RT thread and recover is probably futile. Just
281 # reboot and reset the FTP connection.
282 if (defined $self->{TELNET
}) {
283 $self->{TELNET
}->close();
284 $self->{TELNET
} = undef;
286 $self->{TARGET
}->RebootReset;
289 # Wait until a process exits.
290 # return -1 if the process is still alive.
295 if (!defined $timeout || $timeout < 0) {
296 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
299 $self->{TELNET
}->print("wait");
300 my $reply = $self->{TELNET
}->getline(Timeout
=> 300);
301 $self->{RUNNING
} = 0;
302 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
307 return TimedWait
($self, $timeout);
317 if (!$self->{RUNNING
}) {
322 while ($timeout > 0) {
323 $self->{TELNET
}->print ("status");
324 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
327 $reply = $self->{TELNET
}->getline(Timeout
=> $timeout);
328 if (!defined $reply) {
331 if (defined $ENV{'ACE_TEST_VERBOSE'}) {
334 if ($reply =~ /^RUNNING/) {
339 # Have a status; return it.
340 $self->{RUNNING
} = 0;
351 my $procmask = shift;
353 ## NOT IMPLEMENTED YET