Từ hình 4.2 thấy được JPF đã hỗ trợ việc ghi vết thành công. Quá trình thực thi mã nguồn được ghi lại theo từng dòng. Trên mỗi dòng gồm thông tin về tên lớp, tên phương thức, tên hàm được gọi cùng tham số, chỉ số dòng, câu lệnh thực thi.
Bước 2: Phân tích dữ liệu vết và mã nguồn đầu vào
Phân tích dữ liệu vết ngăn xếp thu được bằng cách đọc file vết chương trình phân tích thành các lớp con có chức năng chứa các thông tin về quá trình chạy chương trình như các lớp lưu trữ tên lớp, tên phương thức,…
Trong hình 4.2 có dòng:
MyTest.java:1 : MyMath.sumodd(5);
MyMath.java:4 : int s = 0, i = 1; MyMath.java:5 : while (i < a) { ….
33
Chúng tôi lưu từng dòng vết này vào lớp LineEntry, sau đó phân tích từng giá trị trong lớp LineEntry lấy các thông tin về lớp lưu vào ClassEntry, thông tin về phương thức lưu vào MethodEntry, và thông tin về câu lệnh lưu vào
BranchEntry. Với dữ liệu log trong hình 4.2 phần tử thứ nhất của LineEntry sẽ lưu trữ dữ liệu:
MyTest.java:12 : MyMath.sumodd(5);
Phần tử thứ hai sẽ chứa dữ liệu:
MyMath.java:4 : int s = 0, i = 1; …
Duyệt qua các phần tử LineEntry sẽ trích lọc được thông tin tên lớp, tên phương thức, tên nhánh. Lớp ClassEntry sẽ chứa thông tin tên lớp là MyMath. Lớp MethodEntry sẽ chứa thông tin về phương thức là sumodd. LớpBranchEntry sẽ lưu thông tin lệnh là while(i<a).
Quá trình được thực hiện tương tự khi phân tích mã nguồn. Công cụ sẽ tìm kiếm lớp chứa phương thức cần kiểm thử trong không gian thư mục scr/examples,
lưu tên lớp vào SourceClassEntry. Tiếp theo công cụ đọc mã nguồn và lưu tên phương thức vào lớp SourceMethodEntry, đọc từng dòng lệnh và lưu các câu lệnh vào lớp SourceBranchEntry.
Bước 3: So sánh kết quả thu được ở bước 2 và hiển thị kết quả.
Quá trình phân tích ở bước 2 đã xây dựng các lớp lưu trữ thông tin về mã nguồn và vết chương trình. Chúng tôi so sánh kết quả thu được và hiển thị kết quả được thực thi tại lớp HtmlGenerator. Kết quả hiển thị dưới file html gồm 3 thông tin chính: cột SOURCE hiển thị mã nguồn đầu vào, cột GRAPH hiển thị đồ thị thể hiện độ phủ, cột RESULT hiển thị bộ test case sử dụng kiểm thử, đường thực thi với từng test case và chỉ rõ nếu nhánh trong chương trình chưa được phủ tại mục Branches are not covered.
4.2.2 Ví dụ minh họa cho phƣơng pháp
Để thuận tiện trong việc mô tả phương pháp cũng như thực hiện phần thực nghiệm, phần này chúng tôi xin đưa ra ví dụ minh họa cho phương pháp đã đề xuất. Lấy ví dụ hàm cần kiểm thử là sumodd có chưc năng tính tổng các số lẻ từ 1 đến n trong lớp MyMath.java có mã nguồn như sau:
public static int sumodd(int n) {
int s = 0, i = 1; if (n > 100) n = 100; while (i <= n) { s += i; i += 2;
34
} return s; }
Để lưu vết cần có một ngoại lệ trong quá trình thực hiện chương trình. Ngoại lệ được định nghĩa tại lớp tên MyException.
public class MyException extends RuntimeException{
public MyException(String description){
super(description); } }
Test driver được xây dựng để vừa thực thi các test case vừa xảy ra ngoại lệ nhằm lưu vết ngăn xếp. Ngoại lệ được xác định là rỗng MyException("").
public class MyTest {
public static void main(String[] args) {
sumodd(5);
throw new MyException(""); }
File cấu hình MyTest.jpf được thiết lập các thông số:
target = MyTest listener=gov.nasa.jpf.listener.MyTracer report.console.property_violation=error,trace report.console.show_steps=true report.console.show_location=true report.console.show_source=true
Công cụ chạy thông qua màn hình console. Mở console, di chuyển đến JPF_HOME và chạy command thực thị file MyTest.jpf
D:\new\jpf\jpf-core>java -jar build/RunJPF.jar src/examples/MyTest.jpf
Kết quả thu được gồm hai file MyTest.html và MyTest.log nằm trong thư mục JPF_HOME\report.