軟件測試中Ns2中的測試用例Ns2中的測試用例
在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); 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; } |
3 代碼使用說明
1.在使用此代碼進行測試前還必須安裝ActivePerl,gawk,UnxUtils這幾個軟件包并配置好相應的路徑。
2.然后修改misc-simple.tcl文件,將其中set quiet false這行語句去掉,否則測試時將不斷調用xgraph,影響連續測試。
3.如果運行nstest不帶任何參數,則運行所有的測試直到測試出來錯誤。
也可以用nstest test_name這樣的方式調用,其中的test_name只要使用test-suite-*.tcl中的星號部分就可以了,如nstest adaptive-red。
4測試中發現的問題
有一些測試無法通過,估計是由于編譯器的差異引起的,如有一些測試生成的數據是5.623,而供比較用的數據是5.622,且只有一兩個地方不一致,因此在代碼中做了處理,允許這種不一致。再如3.2e-05和3.2e-005這樣的差異也認為不是錯誤。
另外有一些則差別很遠,如test-suite-broken.tcl,原因暫時不明,思考中。。。。。
文章來源于領測軟件測試網 http://www.kjueaiud.com/