mirror of https://gitee.com/Nocallback/dejagnu.git
9 changed files with 553 additions and 44 deletions
@ -0,0 +1,215 @@ |
|||||
|
/*
|
||||
|
* Copyright (C) 2000, 2001 Free Software Foundation, Inc. |
||||
|
* |
||||
|
* This program is free software; you can redistribute it and/or modify |
||||
|
* it under the terms of the GNU General Public License as published by |
||||
|
* the Free Software Foundation; either version 2 of the License, or |
||||
|
* (at your option) any later version. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
* GNU General Public License for more details. |
||||
|
|
||||
|
* You should have received a copy of the GNU General Public License |
||||
|
* along with this program; if not, write to the Free Software |
||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
|
*/ |
||||
|
|
||||
|
/* This is the include generated by configuring */ |
||||
|
#include <config.h> |
||||
|
|
||||
|
#ifndef __DEJAGNU_H__ |
||||
|
#define __DEJAGNU_H__ |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
|
||||
|
static int passed; |
||||
|
static int failed; |
||||
|
static int untest; |
||||
|
static int unresolve; |
||||
|
|
||||
|
inline void |
||||
|
pass (const char *s) { |
||||
|
passed++; |
||||
|
printf ("\tPASSED: %s\n", s); |
||||
|
} |
||||
|
|
||||
|
inline void |
||||
|
fail (const char *s) { |
||||
|
failed++; |
||||
|
printf ("\tFAILED: %s\n", s); |
||||
|
} |
||||
|
|
||||
|
inline void |
||||
|
untested (const char *s) { |
||||
|
untest++; |
||||
|
printf ("\tUNTESTED: %s\n", s); |
||||
|
} |
||||
|
|
||||
|
inline void |
||||
|
unresolved (const char *s) { |
||||
|
unresolve++; |
||||
|
printf ("\tUNRESOLVED: %s\n", s); |
||||
|
} |
||||
|
|
||||
|
inline void |
||||
|
totals (void) { |
||||
|
printf ("\nTotals:\n"); |
||||
|
printf ("\t#passed:\t\t%d\n", passed); |
||||
|
printf ("\t#failed:\t\t%d\n", failed); |
||||
|
if (untest) |
||||
|
printf ("\t#untested:\t\t%d\n", untest); |
||||
|
if (unresolve) |
||||
|
printf ("\t#unresolved:\t\t%d\n", unresolved); |
||||
|
} |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <iomanip> |
||||
|
#include <fstream> |
||||
|
#include <string> |
||||
|
#include <strstream> |
||||
|
|
||||
|
char *outstate[] = { |
||||
|
"FAILED: ", |
||||
|
"PASSED: ", |
||||
|
"UNTESTED: ", |
||||
|
"UNRESOLVED: " |
||||
|
}; |
||||
|
|
||||
|
#if 0 |
||||
|
extern ios& __iomanip_testout (ios&, int); |
||||
|
inline smanip<int> testout (int n) { |
||||
|
return smanip<int> (__iomanip_testout, n); |
||||
|
} |
||||
|
ios & __iomanip_testout (ios& i, int x) { |
||||
|
return i; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
class OMANIP { |
||||
|
private: |
||||
|
T i; |
||||
|
ostream &(*f)(ostream&, T); |
||||
|
public: |
||||
|
OMANIP(ostream& (*ff)(ostream&, T), T ii) : f(ff), i(ii) { |
||||
|
} |
||||
|
friend ostream operator<<(ostream& us, OMANIP& m) { |
||||
|
return m.f(os,m.i); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
ostream& |
||||
|
freakout(ostream& os, int x) { |
||||
|
return os << "FREAKOUT" ; |
||||
|
// return x << "TESTOUT " << x ;
|
||||
|
} |
||||
|
|
||||
|
OMANIP<int> testout(int i) { |
||||
|
return OMANIP<int>(&freakout,i); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
char *testout (int x) { |
||||
|
const int len = 128; |
||||
|
static char buf[len]; |
||||
|
static ostrstream oss(buf, len, ios::out); |
||||
|
oss.seekp(ios::beg); |
||||
|
oss << outstate[x] << ends; |
||||
|
return buf; |
||||
|
} |
||||
|
|
||||
|
enum teststate {FAILED, PASSED,UNTESTED,UNRESOLVED} laststate; |
||||
|
|
||||
|
class TestState { |
||||
|
private: |
||||
|
teststate laststate; |
||||
|
string lastmsg; |
||||
|
public: |
||||
|
TestState(void) { |
||||
|
passed = 0; |
||||
|
failed = 0; |
||||
|
untest = 0; |
||||
|
unresolve = 0; |
||||
|
} |
||||
|
~TestState(void) { |
||||
|
totals(); |
||||
|
}; |
||||
|
|
||||
|
void testrun (bool b, string s) { |
||||
|
if (b) |
||||
|
pass (s); |
||||
|
else |
||||
|
fail (s); |
||||
|
} |
||||
|
|
||||
|
void pass (string s) { |
||||
|
passed++; |
||||
|
laststate = PASSED; |
||||
|
lastmsg = s; |
||||
|
cout << "\t" << testout(PASSED) << s << endl; |
||||
|
} |
||||
|
void pass (const char *c) { |
||||
|
string s = c; |
||||
|
pass (s); |
||||
|
} |
||||
|
|
||||
|
void fail (string s) { |
||||
|
failed++; |
||||
|
laststate = FAILED; |
||||
|
lastmsg = s; |
||||
|
cout << "\t" << testout(FAILED) << s << endl; |
||||
|
} |
||||
|
void fail (const char *c) { |
||||
|
string s = c; |
||||
|
fail (s); |
||||
|
} |
||||
|
|
||||
|
void untested (string s) { |
||||
|
untest++; |
||||
|
laststate = UNTESTED; |
||||
|
lastmsg = s; |
||||
|
cout << "\t" << testout(UNTESTED) << s << endl; |
||||
|
} |
||||
|
void untested (const char *c) { |
||||
|
string s = c; |
||||
|
untested (s); |
||||
|
} |
||||
|
|
||||
|
void unresolved (string s) { |
||||
|
unresolve++; |
||||
|
laststate = UNRESOLVED; |
||||
|
lastmsg = s; |
||||
|
cout << "\t" << testout(UNRESOLVED) << s << endl; |
||||
|
} |
||||
|
void unresolved (const char *c) { |
||||
|
string s = c; |
||||
|
unresolved (s); |
||||
|
} |
||||
|
void totals (void) { |
||||
|
cout << "\t#passed:\t\t" << passed << endl; |
||||
|
cout << "\t#failed:\t\t" << failed << endl; |
||||
|
if (untest) |
||||
|
cout << "\t#untested:\t\t" << untest << endl; |
||||
|
if (unresolve) |
||||
|
cout << "\t#unresolved:\t\t" << unresolve << endl; |
||||
|
} |
||||
|
|
||||
|
friend ostream & operator << (ostream &os, TestState& t) { |
||||
|
return os << "\t" << outstate[t.laststate] << t.lastmsg ; |
||||
|
} |
||||
|
|
||||
|
int GetState(void) { |
||||
|
return laststate; |
||||
|
} |
||||
|
string GetMsg(void) { |
||||
|
return lastmsg; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#endif // __cplusplus
|
||||
|
#endif // _DEJAGNU_H_
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,174 @@ |
|||||
|
# a hairy pattern to recognize text |
||||
|
set text "\[- A-Za-z0-9\.\;\"\_\:\'\`\(\)\!\#\=\+\?\&\*]" |
||||
|
|
||||
|
set SIZE size |
||||
|
if { [which $SIZE] == 0 } { |
||||
|
perror "Can't find $SIZE." |
||||
|
} |
||||
|
|
||||
|
# Get the size of the various section in an object file |
||||
|
proc exe_size {object} { |
||||
|
global SIZE |
||||
|
|
||||
|
# Make sure size exists |
||||
|
if { [which $SIZE] == 0 } { |
||||
|
return [list "-1" "Can't find $SIZE."] |
||||
|
} else { |
||||
|
verbose "Using $SIZE for \"size\" program." 2 |
||||
|
} |
||||
|
set status [catch "exec $SIZE -V" output] |
||||
|
if {[regexp "GNU size" $output] == 0} { |
||||
|
perror "Need GNU size from the binutils" 0 |
||||
|
return [list "-1" "Need GNU size."] |
||||
|
} |
||||
|
|
||||
|
# Get the object size. We pass -x, to force hex output |
||||
|
verbose "Getting the object file size for $object" 2 |
||||
|
set status [catch "exec $SIZE -x $object" output] |
||||
|
verbose -log "Size of $object is\n$output" 2 |
||||
|
|
||||
|
# Remove the header line from the size output. This currently only |
||||
|
# works with GNU size |
||||
|
regsub "text.*filename\[\r\n\]*" $output "" output |
||||
|
|
||||
|
# look for the size of the .text section |
||||
|
regexp "\[\r\n\]*0x\[0-9a-fA-F\]*" $output text |
||||
|
regsub "\[\r\n\]*0x\[0-9a-fA-F\]*\[ \t\]*" $output "" output |
||||
|
|
||||
|
# look for the size of the .data section |
||||
|
regexp "0x\[0-9a-fA-F\]*\[ \t\]*" $output data |
||||
|
regsub "0x\[0-9a-fA-F\]*\[ \t\]*" $output "" output |
||||
|
|
||||
|
# Values returns as hex |
||||
|
return [list $text $data] |
||||
|
} |
||||
|
|
||||
|
# Run the host's native compiler, not the cross one. Filter out the |
||||
|
# warnings and other extraneous stuff. |
||||
|
# Returns: |
||||
|
# A "" (empty) string if everything worked, or the |
||||
|
# output if there was a problem. |
||||
|
proc host_compile {compline} { |
||||
|
global INCLUDES |
||||
|
global LIBS |
||||
|
global CXX, CC |
||||
|
|
||||
|
# execute the compiler |
||||
|
verbose "Compiling for the host using: $CC $INCLUDES $LIBS $compline" 2 |
||||
|
set status [catch "exec $CC $INCLUDES $LIBS $compline" comp_output]; |
||||
|
verbose "Compiler returned $comp_output" 2 |
||||
|
|
||||
|
# prune common warnings and other stuff we can safely ignore |
||||
|
set comp_output [prune_warnings $comp_output]; |
||||
|
|
||||
|
# Trim multiple CR/LF pairs out to keep things consistant |
||||
|
regsub "^\[\r\n\]+" $comp_output "" comp_output; |
||||
|
|
||||
|
# if we got a compiler error, log it |
||||
|
if { [lindex $status 0] != 0 } { |
||||
|
verbose -log "compiler exited with status [lindex $status 0]"; |
||||
|
} |
||||
|
if { [lindex $status 1] != "" } { |
||||
|
verbose -log "output is:\n[lindex $status 1]" 2; |
||||
|
} |
||||
|
|
||||
|
# return the filtered output |
||||
|
return ${comp_output} |
||||
|
} |
||||
|
|
||||
|
# Execute the executable file, and anaylyse the output for the |
||||
|
# test state keywords. |
||||
|
# Returns: |
||||
|
# A "" (empty) string if everything worked, or an error message |
||||
|
# if there was a problem. |
||||
|
proc host_execute {args} { |
||||
|
global text |
||||
|
|
||||
|
set timeoutmsg "Timed out: Never got started, " |
||||
|
set timeout 100 |
||||
|
set file all |
||||
|
set timetol 0 |
||||
|
set arguments "" |
||||
|
|
||||
|
expect_before buffer_full { perror "Buffer full" } |
||||
|
|
||||
|
if { [llength $args] == 0} { |
||||
|
set executable $args |
||||
|
} else { |
||||
|
set executable [string trimleft [lindex [split $args " "] 0] "\{"] |
||||
|
set params [string trimleft [lindex [split $args " "] 1] "\{"] |
||||
|
set params [string trimright $params "\}"] |
||||
|
} |
||||
|
|
||||
|
verbose "The executable is $executable" 2 |
||||
|
if ![file exists ${executable}] { |
||||
|
perror "The executable, \"$executable\" is missing" 0 |
||||
|
return "No source file found" |
||||
|
} |
||||
|
|
||||
|
# spawn the executable and look for the DejaGnu output messages from the |
||||
|
# test case. |
||||
|
# spawn -noecho -open [open "|./${executable}" "r"] |
||||
|
spawn -noecho "./${executable}" ${params} |
||||
|
expect { |
||||
|
-re "\[0-9\]\[0-9\]:..:..:${text}\r\n" { |
||||
|
regsub "\[\n\r\t\]*NOTE: " $expect_out(0,string) "" output |
||||
|
verbose "$output" 3 |
||||
|
set timetol 0 |
||||
|
exp_continue |
||||
|
} |
||||
|
-re "NOTE:${text}*" { |
||||
|
regsub "\[\n\r\t\]*NOTE: " $expect_out(0,string) "" output |
||||
|
verbose "$output" 2 |
||||
|
set timetol 0 |
||||
|
exp_continue |
||||
|
} |
||||
|
-re "PASSED:${text}*" { |
||||
|
regsub "\[\n\r\t\]*PASSED: " $expect_out(0,string) "" output |
||||
|
pass "$output" |
||||
|
set timetol 0 |
||||
|
exp_continue |
||||
|
} |
||||
|
-re "FAILED:${text}*" { |
||||
|
regsub "\[\n\r\t\]*FAILED: " $expect_out(0,string) "" output |
||||
|
fail "$output" |
||||
|
set timetol 0 |
||||
|
exp_continue |
||||
|
} |
||||
|
-re "UNTESTED:${text}*" { |
||||
|
regsub "\[\n\r\t\]*TESTED: " $expect_out(0,string) "" output |
||||
|
untested "$output" |
||||
|
set timetol 0 |
||||
|
exp_continue |
||||
|
} |
||||
|
-re "UNRESOLVED:${text}*" { |
||||
|
regsub "\[\n\r\t\]*UNRESOLVED: " $expect_out(0,string) "" output |
||||
|
unresolved "$output" |
||||
|
set timetol 0 |
||||
|
exp_continue |
||||
|
} |
||||
|
-re "Totals" { |
||||
|
verbose "All done" 2 |
||||
|
} |
||||
|
eof { |
||||
|
# unresolved "${executable} died prematurely" |
||||
|
# catch close |
||||
|
# return "${executable} died prematurely" |
||||
|
} |
||||
|
timeout { |
||||
|
warning "Timed out executing test case" |
||||
|
if { $timetol <= 2 } { |
||||
|
incr timetol |
||||
|
exp_continue |
||||
|
} else { |
||||
|
- catch close |
||||
|
return "Timed out executing test case" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
# force a close of the executable to be safe. |
||||
|
catch close |
||||
|
return "" |
||||
|
} |
||||
|
|
||||
Loading…
Reference in new issue