技术开发 频道

Ns2中的测试用例

【IT168 技术文章】

    1测试用例说明

   在NS2的源代码包中包含了几乎所有协议的测试代码,全部存放在ns2\tcl\test目录下,即test-suite-*.tcl这样的文件。每个文件基本就对应一个协议,而且有一个对应的输出目录存放供比较用的运行结果。在运行test-suite-*.tcl之后将会产生一个temp.rands文件,只要这个文件和相应目录下的文件比较相一致就说明NS2的安装是正确的。

   如test-suite-adaptive-red.tcl这个文件的对应目录就是test-output-adaptive-red。
   每个测试用的tcl文件中都使用了一个或多个测试用例,因此output目录下也对应有一个或者多个文件,这些供比较用的文件都是用gzip压缩的,比较前应先解压缩。通过ns test-suite-*.tcl这样的命令可以知道每个TCL文件所支持的测试用例。使用ns test-suite-*.tcl test_name这样的格式就可以调用指定的测试用例。

   如Ns test-suite-adaptive-red.tcl red1
   就指明了要调用red1这个测试用例,运行之后在测试目录下生成temp.rands文件,将这个文件与test-output-adaptive-red\red1.Z解压缩后的文件进行比较即可。

   2测试代码

   在此测试目录下同时提供了完整的测试Shell代码,不过很遗憾在windows下没法运行(需要cygwin),于是自己动手写了下面的C++代码进行完整的测试。


// NsTest.cpp : 定义控制台应用程序的入口点。 
//

#include "stdafx.h"
#include <windows.h>
#include <fstream>
#include <math.h>
using namespace std;

#define TEST_PATH "d:\\temp\\test\\"
#define FIND_MASK "d:\\temp\\test\\test-suite-*.tcl"
#define NS_PATH "d:\\research\\debug\\ns-2.31.exe"


void Compare(char* f1, char* f2)
{
// 比较两个文件是否相同,之所以不用cmp进行比较,是因为在不同版本生成的数据中输出格式可能会不一致,
// 主要是科学计数法输出的不一致,如提供的原始数据为.2e-05,而生成的数据为.2e-005


ifstream s1(f1);
ifstream s2(f2);
if(s1.is_open() && s2.is_open())
{
char line1[2048], line2[2048];
int nLine = 0;
while(!s1.eof() && !s2.eof())
{
nLine++;
s1.getline(line1, 2048);
s2.getline(line2, 2048);
if(strcmp(line1, line2) == 0) continue;
double d[4];
sscanf(line1, "%lf %lf", &d[0], &d[1]);
sscanf(line2, "%lf %lf", &d[2], &d[3]);
if(fabs(d[0] - d[2]) > 0.00005 || fabs(d[1] - d[3]) > 0.005)
{
printf("%s and %s compare failed: \nline: %d\n%s\n%s\n", f1, f2, nLine, line1, line2);
s1.close();
s2.close();
exit(1);
}
}
if(s1.eof() && !s2.eof())
{
printf("%s and %s compare failed: s1.eof() && !s2.eof()", f1, f2);
s1.close();
s2.close();
exit(1);
}
else if(!s1.eof() && s2.eof())
{
printf("%s and %s compare failed: !s1.eof() && s2.eof()", f1, f2);
s1.close();
s2.close();
exit(1);
}
}
else
{
printf("compare file open failed: \n%s\n%s\n", f1, f2);
s1.close();
s2.close();
exit(1);
}
s1.close();
s2.close();

}

void Exec(char *cmd)
{
DWORD code = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );


// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line).
cmd, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
TEST_PATH, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
printf( "%s failed (%d).\n", cmd, GetLastError() );
exit(1);
}
WaitForSingleObject( pi.hProcess, INFINITE );
GetExitCodeProcess(pi.hProcess, &code);
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
if(code != 0)
{
printf("%s failed with code (%d)\n", cmd, code);
exit(code);
}
}

bool IsComment(char* p)
{
while((*p == ' ' || *p == '\t') && *p != 0) p++;
return *p == '#';
}

void ProcessOneFile(char* file_name)
{
// 处理一个文件
char tcl_file[MAX_PATH];
sprintf(tcl_file, "%stest-suite-%s.tcl", TEST_PATH, file_name);
ifstream src(tcl_file);
if(!src.is_open())
{
printf("%s open failed!\n", tcl_file);
return;
}
sprintf(tcl_file, "%s_tmp.tcl", TEST_PATH);
FILE* dst = fopen(tcl_file, "wt");
if(dst == NULL)
{
printf("create temp tcl failed\n");
src.close();
return;
}
fprintf(dst, "set PERL {perl}\n");
fprintf(dst, "set quiet true\n");
char cClass[1000][100];
int nClass = 0;
while(!src.eof())
{
char line[2048];
char* p;
src.getline(line, 2048);
if(IsComment(line)) continue;
if(strstr(line, "Class") && (p = strstr(line, "Test/")))
{
int idx = 0;
p += 5;
while(*p != 0 && *p != ' ') cClass[nClass][idx++] = *p++;
cClass[nClass][idx] = 0;
nClass++;
}
else if(strstr(line, "xgraph"))
{
fprintf(dst, "#");
}
fprintf(dst, "%s\n", line);
}
src.close();
fclose(dst);

// 执行TCL文件并进行比较
for(int i = 0; i < nClass; i++)
{
printf("%s testcase begin...", cClass[i]);

char cmd[2560];
sprintf(cmd, "%s %s_tmp.tcl %s", NS_PATH, TEST_PATH, cClass[i]);
Exec(cmd);

// 备份压缩文件
sprintf(cmd, "cp %stest-output-%s\\%s.Z %stest-output-%s\\%s_bak.Z", TEST_PATH, file_name, cClass[i], TEST_PATH, file_name, cClass[i]);
Exec(cmd);

// 解压缩
sprintf(cmd, "gzip -daf %stest-output-%s\\%s.Z", TEST_PATH, file_name, cClass[i]);
Exec(cmd);

// 还原压缩文件
sprintf(cmd, "mv %stest-output-%s\\%s_bak.Z %stest-output-%s\\%s.Z", TEST_PATH, file_name, cClass[i], TEST_PATH, file_name, cClass[i]);
Exec(cmd);

// 比较文件
char f1[MAX_PATH], f2[MAX_PATH];
sprintf(f1, "%stest-output-%s\\%s", TEST_PATH, file_name, cClass[i]);
sprintf(f2, "%stemp.rands", TEST_PATH);
Compare(f1, f2);

// 删除解压缩后的文件
sprintf(cmd, "rm -f %stest-output-%s\\%s", TEST_PATH, file_name, cClass[i]);
Exec(cmd);

printf("OK\n");
}

}

int _tmain(int argc, _TCHAR* argv[])
{
// 查找测试文件所在目录下的所有文件
WIN32_FIND_DATA fdata;
HANDLE hFind = FindFirstFile(FIND_MASK, &fdata);
if(hFind == INVALID_HANDLE_VALUE)
{
printf("find file failed");
return 1;
}
do
{
bool bProcess = false;
if(argc > 1)
{
for(int i = 1; i < argc; i++)
{
if(strstr(fdata.cFileName, argv[i]))
{
bProcess = true;
break;
}
}
}
else
bProcess = true;
if(bProcess)
{
printf("\n%s processing...\n", fdata.cFileName);
fdata.cFileName[strlen(fdata.cFileName) - 4] = 0;
ProcessOneFile(fdata.cFileName + strlen("test-suite-"));
}
}while(FindNextFile(hFind, &fdata));
FindClose(hFind);

printf("all file processed\n");
getchar();
return 0;

0
相关文章