Luận văn Kiểm chứng đặt tả uml cho tác tử phần mềm

Trong phương pháp kiểm chứng các đặc tả giao thức cho ứng dụng, các mô-đun aspect chứa mã kiểm chứng sẽ là các mô-đun cắt ngang hệ thống và tách biệt so với chương trình ban đầu. Từ biểu đồ trạng thái hay biểu đồ trình tự UML, AUML đặc tả giao thức, tôi xuất biểu đồ này ra dạng tài liệu XMI.

pdf93 trang | Chia sẻ: lylyngoc | Lượt xem: 2364 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Luận văn Kiểm chứng đặt tả uml cho tác tử phần mềm, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
g hoàn chỉnh. - Thêm nữa, để quản lý trạng thái của SharedState, ta cần phải có dữ liệu của FSM mô tả biểu đồ trình tự UML. Vì vậy, trong aspect này sẽ chứa thêm phần mã nguồn tạo ra FSM từ biểu đồ trình tự UML như trong chương 4 đã trình bày. 5.4 Mở rộng Trong bài báo “Checking Interface Interaction Protocols Using Aspect-oriented Programming” [5] chưa xử lý các hàm trùng tên nhưng có các tham s ố truyền vào khác nhau hay kiểu dữ liệu trả về khác nhau và không kiểm tra điều kiện tiên quyết cần thiết trước khi hàm được gọi (precondition của hàm). Trong khóa luận của tôi, tôi đã mở rộng thêm hai phần này: - Kiểm tra precondition được mô tả trong biểu đồ trạng thái UML: Như trong phần 4.1.1, tôi có nói đến các quy tắc biểu diễn giao thức bằng biểu đồ trạng thái UML. Biểu thức điều kiện ở đây giống với biểu thức điều kiện trong mã nguồn của chương trình. Như v ậy, để kiểm tra xem có vi phạm điểu kiện hay không, tôi sẽ quy về một đoạn mã nguồn có thể là biểu thức, có thể chứa các lời gọi hàm và trả về kiểu boolean. Như vậy ta sẽ kiểm tra được vi phạm. Tuy nhiên, do việc mô tả precondition bằng cách rất hạn chế mà công cụ PVG chỉ tạo ra aspect với các mô tả có trong biểu đồ, do đó đôi khi precondition sẽ không kiểm tra được trong thực tế (ví dụ: precondition liên quan đến dữ liệu của nhiều lớp khác nhau chẳng hạn). Điều này có thể khắc phục bằng cách sửa lại mô-đun aspect do công cụ PVG tạo ra, thêm một số các đoạn mã để có thể kiểm tra được precondition trong mô-đun aspect. 52 - Thêm tham số truyền vào cho hàm: ở đây tôi sử dụng các thao tác với xâu khí tự trong Java, cắt chuỗi phương thức thành các phần nhỏ như: các chuỗi lưu tên hàm, tên tham số truyền vào, tên kiểu dữ liệu của tham số, tên tham số, kiểu giá trị trả về từ đó tạo ra các advice bằng cách thay thế các chuỗi con này vào trong các phần của aspect mẫu đã được định nghĩa từ trước. Khi cắt xâu ký tự mô tả phương thức thành nhiều phần nhỏ như vậy, việc tạo ra hai pointcut cho hai hàm trùng tên nhưng khác tham số truyền vào rất đơn giản, tôi chỉ cần thêm chuỗi mô tả kiểu của các tham số vào ngay sau xâu định nghĩa tên pointcut; như vậy sẽ giải quyết được mọi vấn đề của các hàm trùng tên, khác tham số truyền vào. 5.5 Sinh mã aspect kiểm chứng giao thức (AB)n Trong phần tìm hiểu của tôi, tôi sử dụng phương pháp tạo ra mã kiểm chứng ở trên để xây dựng thêm một chức năng khác cho công cụ “PVG”, đó là sinh mã aspect kiểm chứng giao thức (AB)n. Trong phần này tôi sẽ trình bày phần mở rộng này. 5.5.1 Giao thức (AB)n là gì? A và B là tên của các phương thức còn n là số lần các phương thức được gọi trong chương trình. Nói một cách đơn giản, (AB)n mô tả việc hàm A và B phải được gọi n lần trong mã nguồn của chương trình. Giao thức (AB)n được mô tả bằng biểu thức chính quy như sau: [A*B] n. Ở đây, * có thể là rỗng (null) hoặc là một dãy các phương thức khác. Ví dụ: - Giao thức: [void open() void close()]3 - mô tả việc gọi 3 cặp phương thức void open(), void close() trong chương trình; gi ữa hai phương thức này không có bất kỳ phương thức nào khác được gọi: - …open() close()…open() close()…open() close()… - Giao thức: [void open() * void close()]3 – mô tả việc gọi cặp hàm void open() và void close() trong chương trình như sau: - …open()…close()…open()…close()…open()…close(). Ở đây “…” đại diện cho một phương thức hay một chuỗi phương thức bất kỳ. Công cụ PVG chỉ hiểu giao thức (AB)n được định nghĩa theo đúng như biểu thức chính quy mô tả ở trên. 53 5.5.2 Thuật toán kiểm chứng giao thức (AB)n 5.5.2.1 [A * B] n Việc kiểm chứng giao thức [A * B] n nảy sinh hai vấn đề lớn: - Thứ nhất: phương thức A và B được gọi liên tiếp nhau (), tức là việc gọi hai phương thức A B phải tạo thành một dãy: A … B … A … B… Vấn đề này được giải quyết bằng một biến đếm kiểu nguyên num như sau: o Ban đầu đặt num = 0. o Trước khi gọi A, kiểm tra num, nếu num != 0 -> báo lỗi o Sau khi gọi A, tăng num lên 1. o Sau khi gọi B, giảm num đi 1. Và sau khi giảm n đi 1 kiểm tra num, nếu num != 0 -> báo lỗi. - Thứ hai: cặp (A B) được gọi đúng n lần. Việc gọi cặp (A B) đúng n lần nảy sinh ra hai trường hợp: gọi lớn hơn n lần và gọi nhỏ hơn n lần. Kiểm tra cặp A, B gọi đúng lớn hơn n lần rất đơn giản, ta cũng dùng một biến kiểu nguyên khác để kiểm tra (ví dụ: biến int count): o Sau khi gọi A, tăng biến count lên 1 và kiểm tra, nếu count > n thì báo lỗi. o Ở đây ta chỉ cần kiểm tra A có được gọi > n lần hay không mà không cần kiểm tra B vì nếu A đã được gọi > n lần thì ta đã bắt được lỗi và nếu A và B được gọi với số lần khác nhau, ta cũng đã b ắt được lỗi bằng biến num ở trên. Như vậy chỉ cần kiểm tra A là đủ. Kiểm tra (A B) được gọi < n lần khó khăn hơn, ta không thể dùng các join point tại các phương thức A và B kiểm tra được mà phải dùng một join point khác là điểm mà sau khi tất cả các hàm A, B được gọi. Để đơn giản, tôi tạo ra một phương thức mới trong mã nguồn của chương trình (void checkAnBn()). Phương thức này không ảnh hưởng gì đ ến chương trình, nó đư ợc gọi ở điểm kết thúc của chương trình. Sau khi tạo được một join point tại điểm kết thúc của chương trình thì vi ệc kiểm tra A có được gọi n lần hay không tôi cũng dùng chính ngay biến count ở trên để kiểm tra. Before advice sẽ kiểm tra xem, nếu count != n thì sẽ báo lỗi. Quay trở lại, ta có thể thấy việc tạo ra một phương thức mới làm điểm đánh dấu kết thúc chương trình sẽ giải quyết được tất cả vấn đề 54 liên quan tới việc gọi hàm A đúng n lần. Trong công cụ PVG tôi sử dụng cả hai cách đã được chỉ ra ở trên. 5.5.2.2 [A B] n [A B] n là mở trường hợp đặc biệt của [A * B] n khi * = null. Ở đây, ta phải gọi hai phương thức A, B theo một cặp (A B). Để kiểm chứng giao thức [A B] n ta cũng kế thừa từ thuật toán kiểm chứng giao thức [A * B] n, và mở rộng thêm một phần kiểm tra gọi hai phương thức A, B theo cặp (A B). Để làm được điều này, ta phải bắt được tất cả các điểm gọi hàm khác. Khi bắt được tất cả các điểm gọi hàm khác thì việc kiểm tra vi phạm sẽ rất đơn giản, ta chỉ cần dùng một biến check kiểu nguyên. Mỗi khi chương trình g ọi hàm, biến check được tăng lên 1. Sau khi chương trình gọi hàm A, biến check được đặt lại giá trị = 0. Và ta sẽ kiểm tra sau khi gọi hàm B, nếu biến check != 1 thì chương trình sẽ báo lỗi. Vì nếu check != 1 thì tức là đã có một hàm khác được gọi ở giữa A và B. 5.5.3 Sinh mã aspect kiểm chứng giao thức (AB)n Phương pháp này có ý tưởng hoàn toàn giống với phương pháp sinh aspect kiểm chứng từ biểu đồ UML, nó chỉ khác nhau ở các mẫu aspect được định nghĩa khác nhau. Đầu tiên là phân tích chuỗi [A * B] n lấy ra các phương thức A, B và biến n. Sau đó dùng các phương thức xử lý xâu ký tự, tách các hàm A, B này ra thành các phần: tên hàm, kiểu giá trị trả về, tham số… giống như khi xử lý tạo ra aspect từ biểu đồ UML. Sau đó tạo ra các aspect theo mẫu đã định nghĩa trước. 5.6 Kết luận Trong chương này, tôi đã trình bày phương pháp tự động sinh mô-đun aspect từ FSM mô tả biểu đồ UML. Nội dung chính của phương pháp chính là duyệt các trạng thái trong FSM, phân tích vào các vị trí thích hợp trong xâu aspect mẫu được khai báo từ trước. Xâu aspect mẫu sẽ tuân theo cú pháp của một aspect cơ bản, bao gồm tên aspect, vùng pointcut và vùng advice. Thuật toán duyệt các trạng thái trong máy trạng thái thực chất là việc duyệt các key của FSM, lấy dữ liệu của từng trạng thái, sử dụng các phương thức thao tác với xâu ký tự để tạo ra các aspect. Đồng thời, tôi đưa ra phương pháp kiểm chứng giao thức (AB)n – một mở rộng cho công cụ PVG có thể kiểm chứng giao thức (AB)n. Kết quả thu được sau bước này là mã aspect. Mã aspect này sẽ được đan vào chương trình chính để thực hiện chức năng kiểm chứng chương trình. 55 Chương 6. Thực nghiệm Để minh họa cho phương pháp xây dựng công cụ sinh aspect được giới thiệu trong các chương trước, chương này sẽ mô tả chi tiết các bước cài đặt mà tôi đã thực hiện và kết quả thực hiện kiểm chứng trên một số giao thức thực tế. 6.1 Xây dựng công cụ PVG Sau khi đặc tả giao thức cần kiểm chứng bằng UML, công cụ StarUML ( hỗ trợ xuất biểu đồ UML ra dạng XMI và đây chính là đầu vào cho công cụ PVG của tôi. Áp dụng phương pháp được giới thiệu ở các chương trước, tôi đã cài đ ặt thành công chương trình tự sinh mã aspect từ tài liệu XMI. Trong phương pháp này, tôi sử dụng công cụ Netbeans 6.5 với framework JDK để cài đặt công cụ. Giao diện làm việc trên Netbeans 6.5 được minh họa như sau: Hình 6.1: Cài đặt PVG bằng công cụ Netbeans 6.5 Thuật toán cơ bản của phương pháp này là việc phân tích tài liệu XMI, xây dựng các cấu trúc dữ liệu để mô tả biểu đồ UML bằng các đối tượng trong Java. Từ đó xây dựng máy trạng thái. Duyệt các trạng thái trong máy trạng thái, phân tích vào các vị trí thích hợp trong xâu aspect mẫu được khai báo từ trước. Xâu aspect mẫu sẽ tuân theo cú pháp của một aspect cơ bản, bao gồm tên aspect, vùng pointcut và vùng advice. Thuật toán duyệt các trạng thái trong máy trạng thái thực chất là việc duyệt các key của 56 FSM, lấy dữ liệu của từng trạng thái, sử dụng các phương thức thao tác với xâu ký tự để tạo ra các aspect tương ứng. Cài đặt công cụ thông qua một số bước như: - Bước 1: Tạo ra các cấu trúc dữ liệu mô tả biểu đồ trạng thái và biểu đồ trình tự UML. - Bước 2: Cài đặt thuật toán xây dựng FSM - Bước 3: Cài đặt thuật toán xây dựng bộ sinh tự động mã aspect - Bước 4: Tích hợp thành chương trình hoàn chỉnh. Hoàn tất quá trình cài đặt, tôi thu được công cụ tự sinh mã aspect kiểm chứng. 6.2 Kiểm chứng một số giao thức thực tế 6.2.1 Giao thức của các ứng dụng Applet 6.2.1.1 Giới thiệu Applet protocol Java Applet là một chương trình viết bằng ngôn ngữ Java và được kích hoạt nhờ các trình duyệt web. Hình vẽ dưới đây mô tả giao thức của các ứng dụng applet: Hình 6.2: Biểu đồ trạng thái mô tả giao thức applet Một applet thường có bốn phương thức chính: init, start, stop và destroy. - Init: Để khởi tạo applet mỗi khi applet được nạp hay được nạp lại. - Start: Kích hoạt applet bắt đầu hoạt động. - Stop: Cho phép tạm ngưng thực hiện các hoạt động của applet, nhưng có thể không hoàn trả tài nguyên hệ thống. - Destroy: Hủy applet, giải phóng tài nguyên hệ thống. 57 Các client đầu tiên sẽ gọi phương thức init, sau đó là cặp phương thức start – stop được gọi lặp đi lặp lại tùy mục đích sử dụng. Cuối cùng phương thức destroy được gọi khi client muốn hủy applet. Giao thức applet có thể được mô tả bởi biểu thức chính quy: init (start | stop) + destroy. 6.2.1.2 Kiểm chứng Applet protocol Với giao thức applet mô tả như phần trước, tôi sử dụng công cụ StarUML ( vẽ một biểu đồ trạng thái để mô tả lại giao thức applet dưới dạng biểu đồ trạng thái UML (Hình 6.2) sau đó xuất ra dạng tài liệu XMI làm đầu vào cho công cụ PVG của tôi. Lập trình viên mô tả lớp Applet gồm bốn phương thức: void init(), void start(), void stop() và void destroy(): public class Applet { public void init(){//do something} public void start(){//do something} public void stop(){//do something} public void destroy(){//do something} } Mã aspect sinh ra từ công cụ PVG: public aspect ProtocolChecker{ public final static int STATE_START = 0; public final static int STATE_destroy = STATE_START; public final static int STATE_stop = 2; public final static int STATE_start = 3; public final static int STATE_init = 4; private int state = STATE_START; /* public ProtocolChecker(){ System.out.println("Aspect instance is created: "+this); } */ pointcut pc_stop(): call (void stop()); before(): pc_stop() { if (!(state==STATE_start)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_stop() { state = STATE_stop; } pointcut pc_destroy(): call (void destroy()); before(): pc_destroy() { 58 if (!(state==STATE_stop)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_destroy() { state = STATE_destroy; } pointcut pc_init(): call (void init()); before(): pc_init() { if (!(state==STATE_START)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_init() { state = STATE_init; } pointcut pc_start(): call (void start()); before(): pc_start() { if (!(state==STATE_stop || state==STATE_init)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_start() { state = STATE_start; } } Sau khi sinh aspect kiểm chứng bằng công cụ PVG, tích hợp vào mã nguồn chương trình, tôi được kết quả kiểm thử với một số đầu vào khác nhau như sau: - CorrectTest1: o Chuỗi gọi: init(); start(); stop(); destroy(); o Kết quả: Hình 6.3: Applet – CorrectTest1 59 o Nhận xét: chuỗi gọi đúng với đặc tả giao thức, chương trình không báo lỗi. - CorrectTest2: o Chuỗi gọi: init(); start(); stop(); [start(); stop()]2 destroy(); o Kết quả: Hình 6.4: Applet – CorrectTest2 o Nhận xét: chuỗi gọi đúng với đặc tả giao thức, chương trình không báo lỗi. - WrongTest1: o Chuỗi gọi: init(); stop(); start(); destroy(); o Kết quả: Hình 6.5: Applet – WrongTest1 o Nhận xét: chuỗi gọi sai đặc tả, phương thức stop() được gọi trước phương thức start(), chương trình báo lỗi và chỉ ra dòng mã nguồn bị lỗi. - WrongTest2: o Chuỗi gọi: init(); destroy(); start(); init(); o Kết quả: 60 Hình 6.6: Applet – WrongTest2 o Nhận xét: chuỗi gọi sai đặc tả tại lời gọi ba phương thức destroy(); start(); init(); chương trình bắt được tất cả các lỗi. Như vậy, chỉ mới thực hiện bốn ca kiểm thử, ta có thể thấy rất rõ aspect do công cụ PVG tạo ra đáp ứng được yêu cầu kiểm chứng giao thức applet. Để chính xác hơn, ta hoàn toàn có thể định nghĩa các ca kiểm thử khác để kiểm chứng sự làm việc của aspect này. 6.2.2 Kiểm chứng giao thức biểu diễn giao thức ghi nợ ở một máy ATM 6.2.2.1 Đặc tả giao thức Hình 6.7: Giao thức ghi nợ đơn giản 61 Giao thức mô tả tương tác giữa hai lớp Account và DBManager. Khi một đối tượng Account gọi phương thức debit() một dãy các hàm được gọi phải tuân theo giao thức được định nghĩa để hoàn thành giao dịch: Account.debit() -> Account.getBalance() -> DBManager.queryB() -> Account.setBalance() -> DBManager.updateB(). 6.2.2.2 Kiểm chứng Mã aspect: import java.io.File; import java.util.*; import org.aspectj.lang.JoinPoint; import readXMI_SequenceDiagram.*; public aspect ProtocolChecker { int NUMBER_OF_CLASSES = 2; SharedStateManager sm = new SharedStateManager(NUMBER_OF_CLASSES); static HashMap> fsm = null; static HashSet entrySigs, exitSigs; ProtocolChecker(){ if (fsm == null) loadProtocol(); } pointcut pc_Account_debit(): call (void Account.debit()) ; before(): pc_Account_debit() { Object o = thisJoinPoint.getTarget(); if (!sm.isBinded(o)) sm.newSharedState(o); } after(): pc_Account_debit() { String s = thisJoinPoint.getSignature().toString(); Object o = thisJoinPoint.getTarget(); log("change state: " + sm.getSharedState(o).getState() + " ---> " + s); sm.setSharedState(o, s); } pointcut pc_DBManager_updateB_String(String str): args(str) && call (void DBManager.updateB(String)); before(String str): pc_DBManager_updateB_String(str) { Object o = thisJoinPoint.getTarget(); if (!sm.isBinded(o)) sm.bind(o); String s = thisJoinPoint.getSignature().toString(); if (! isValidState(o, s)) { log("Invalid change: " + sm.getSharedState(o).getState() + " ---> " + s); log(thisJoinPoint); } } after(String str): pc_DBManager_updateB_String(str){ String s = thisJoinPoint.getSignature().toString(); Object o = thisJoinPoint.getTarget(); log("change state: " + sm.getSharedState(o).getState() + " ---> " + s); if (exitSigs.contains(s)) sm.reset(o); } 62 pointcut pc_DBManager_queryB_String(String str): args(str) && call (int DBManager.queryB(String)); before (String str): pc_DBManager_queryB_String(str) { Object o = thisJoinPoint.getTarget(); if (!sm.isBinded(o)) sm.bind(o); String s = thisJoinPoint.getSignature().toString(); if (! isValidState(o, s)) { log("Invalid change: " + sm.getSharedState(o).getState() + " ---> " + s); log(thisJoinPoint); } } after(String str): pc_DBManager_queryB_String(str) { String s = thisJoinPoint.getSignature().toString(); Object o = thisJoinPoint.getTarget(); log("change state: " + sm.getSharedState(o).getState() + " ---> " + s); sm.setSharedState(o, s); } pointcut pc_Account_getBalance(): call (int Account.getBalance()); before (): pc_Account_getBalance() { Object o = thisJoinPoint.getTarget(); if (!sm.isBinded(o)) sm.bind(o); String s = thisJoinPoint.getSignature().toString(); if (! isValidState(o, s)) { log("Invalid change: " + sm.getSharedState(o).getState() + " ---> " + s); log(thisJoinPoint); } } after(): pc_Account_getBalance() { String s = thisJoinPoint.getSignature().toString(); Object o = thisJoinPoint.getTarget(); log("change state: " + sm.getSharedState(o).getState() + " ---> " + s); sm.setSharedState(o, s); } pointcut pc_Account_setBalance_int(int ba): args(ba) && call (void Account.setBalance(int)); before (int ba): pc_Account_setBalance_int(ba) { Object o = thisJoinPoint.getTarget(); if (!sm.isBinded(o)) sm.bind(o); String s = thisJoinPoint.getSignature().toString(); if (! isValidState(o, s)) { log("Invalid change: " + sm.getSharedState(o).getState() + " ---> " + s); log(thisJoinPoint); } } after(int ba): pc_Account_setBalance_int(ba) { String s = thisJoinPoint.getSignature().toString(); Object o = thisJoinPoint.getTarget(); log("change state: " + sm.getSharedState(o).getState() + " ---> " + s); sm.setSharedState(o, s); } void log(JoinPoint jp){ 63 String s = "WRONG: " + jp.getSourceLocation() + ":" + jp.getSignature(); System.out.println(s); } void log(String s) { System.out.println("INF: "+ s); } boolean isValidState(Object o, String st){ boolean b = fsm.containsKey(st); SharedState state = sm.getSharedState(o); String objState = state.getState(); if (b) b = fsm.get(st).contains(objState); return b; } public void loadProtocol(){ try{ File xmlFile = new File ("./src/model/sequence.xml"); SequenceDiagramFSM colfsm = new SequenceDiagramFSM(xmlFile); fsm = colfsm.fsm; entrySigs = colfsm.entrySigs; exitSigs = colfsm.exitSigs; } catch (Exception e) { e.printStackTrace(); } } } Tương tự như với giao thức applet. Lập trình viên sẽ xây dựng hai lớp là Account và DBManager như đã đặc tả. Mã aspect được sinh ra từ công cụ PVG sẽ được kết hợp với mã nguồn của chương trình. Sau đây là một số trường hợp kiểm chứng: - CorrecTest1: o Lời gọi hàm: Account.debit(); ccount.getBalance(); DBManager.queryB("str"); Account.setBalance(1); DBManager.updateB("str"); o Kết quả: called debit() called getBalance() called queryB() called setBalance() called updateB() o Nhận xét: chuỗi gọi hàm đúng với đặc tả giao thức, trong khi chạy không phát sinh lỗi. - WrongTest1: o Lời gọi hàm: 64 Account.debit(); DBManager.queryB("str"); Account.getBalance(); DBManager.queryB("str"); Account.setBalance(1); DBManager.updateB("str"); o Kết quả: Hình 6.8: Debit – wrongTest1 Nhật xét: Chuỗi gọi hàm sai đặc tả tại hai phương thức DBManager.queryB("str"); Account.getBalance();vì vậy khi chạy, chương trình thông báo lỗi tại vị trí gọi hai phương thức này. 6.2.3 Kiểm chứng giao thức [A*B] n Giả sử ta cần kiểm chứng giao thức được mô tả bằng biểu thức chính quy như sau: [void open() * void close()]3 Mã aspect sinh ra từ công cụ PVG: import org.aspectj.lang.JoinPoint; public aspect ABnChecker{ int num = 0; int count = 0; int number = 3; pointcut pc_open(): call (void open()); before(): pc_open() { if (num != 0){ log(thisJoinPoint); }} after(): pc_open() { count++; 65 num++; if(count > number) log(thisJoinPoint); } pointcut pc_close(): call (void close()); after(): pc_close() { num--; if(num != 0 || count > number){ log(thisJoinPoint); }} void log(JoinPoint jp){ String s = "WRONG: " + jp.getSourceLocation() + ":" + jp.getSignature(); System.out.println(s); } pointcut checkn() : call (void checkprotocolAnBn()); after(): checkn() { if(count != number){ System.out.println("protocol is false"); } } /* copy this method to source code public static void checkprotocolAnBn(){ } */ } Dưới đây là kết quả của một số ca kiểm thử được thực hiện sau khi tích hợp mã aspect vào chương trình chính: - WrongTest1: o Chuỗi gọi hàm: connectDB db = new connectDB(); db.open(); db.close(); db.open(); db.close(); o Kết quả: called open() called close() called open() called close() protocol is false - WrongTest2: o Chuỗi gọi hàm: connectDB db = new connectDB(); db.open(); db.open(); db.close(); 66 db.close(); db.open(); db.close(); o Kết quả: called open() WRONG: CheckAxBn.java:40:void connectDB.open() called open() called close() WRONG: CheckAxBn.java:41:void connectDB.close() called close() called open() called close() - Nhận xét: Cả hai ca kiểm thử, chuỗi gọi hàm đều sai với đặc tả và trong khi chạy, chương trình đều báo lỗi. 6.2.4 Kiểm chứng giao thức tương tác tác tử 6.2.4.1 Đặc tả giao thức Hình 6.9: Tương tác giữa hai tác tử Khach hang và Gio hang Hình vẽ trên mô tả kịch bản đặt hàng của khách hàng trong một hệ thống bán hàng. Có hai tác tử tham gia: Khach hang và Gio hang. Để đặt hàng, đầu tiên khách hàng gửi yêu cầu đặt hàng. Khi nhận được yêu cầu đặt hàng của khách hàng, giỏ hàng có thể chấp nhận yêu cầu, từ chối yêu cầu hoặc đưa ra một lời đề nghị sửa đổi cho 67 khách hàng. Nhận được lời đề nghị từ phía giỏ hàng, khách hàng có thể chấp nhận hoặc hủy bỏ lờ đề nghị. Sau đó, giỏ hàng có thể chấp nhận yêu cầu đặt hàng hoặc đưa ra thông báo lỗi trả về cho khách hàng. Giao thức cũng có thể định nghĩa bằng biểu đồ trạng thái UML như sau: Hình 6.9: Biểu đồ trạng thái biểu diễn giao thức tương tác tác tử Lập trình viên sẽ cài đặt agent Customer đại diện cho khách hàng có hai hành vi chính: - Gửi thông điệp yêu cầu đặt hàng. - Trả lời đề nghị từ phía giỏ hàng. Agent ShoppingCart đại diện cho agent Gio hang, cũng có hai hành vi chính: - Trả lời yêu cầu đặt hàng của khách hàng. - Gửi lời đề nghị cho khách hàng. Mã nguồn cụ thể tôi giới thiệu trong Phụ lục C và D của khóa luận. 6.2.4.2 Kiểm chứng Mã aspect sinh ra từ công cụ PVG: public aspect ProtocolChecker{ public final static int STATE_START = 0; public final static int STATE_refuseRequest = STATE_START; public final static int STATE_agreeRequest = STATE_START; public final static int STATE_sendSuggest = 2; public final static int STATE_refuseSuggest = 3; public final static int STATE_sendRequest = 3; public final static int STATE_agreeSuggest = 3; private int state = STATE_START; public ProtocolChecker(){ System.out.println("Aspect instance is created: "+this); 68 } pointcut pc_refuseSuggest(): call (void refuseSuggest()); before(): pc_refuseSuggest() { if (!(state==STATE_sendSuggest)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_refuseSuggest() { state = STATE_refuseSuggest; } pointcut pc_refuseRequest(): call (void refuseRequest()); before(): pc_refuseRequest() { if (!(state==STATE_refuseSuggest || state==STATE_sendRequest || state==STATE_agreeSuggest)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_refuseRequest() { state = STATE_refuseRequest; } pointcut pc_sendSuggest(): call (void sendSuggest()); before(): pc_sendSuggest() { if (!(state==STATE_refuseSuggest || state==STATE_sendRequest || state==STATE_agreeSuggest)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_sendSuggest() { state = STATE_sendSuggest; } pointcut pc_sendRequest(): call (void sendRequest()); before(): pc_sendRequest() { if (!(state==STATE_START)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_sendRequest() { state = STATE_sendRequest; } 69 pointcut pc_agreeSuggest(): call (void agreeSuggest()); before(): pc_agreeSuggest() { if (!(state==STATE_sendSuggest)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_agreeSuggest() { state = STATE_agreeSuggest; } pointcut pc_agreeRequest(): call (void agreeRequest()); before(): pc_agreeRequest() { if (!(state==STATE_refuseSuggest || state==STATE_sendRequest || state==STATE_agreeSuggest)){ System.out.print("Wrong at: "+thisJoinPointStaticPart.getSignature()); System.out.print(" In file: "+thisJoinPointStaticPart.getSourceLocation().getFileName()); System.out.println(" At line: "+thisJoinPointStaticPart.getSourceLocation().getLine()); }} after(): pc_agreeRequest() { state = STATE_agreeRequest; } } Tích hợp mã aspect này vào chương trình chính, tôi thực hiện một số ca kiểm thử và thu được kết quả như sau: - WrongTest1: Agent Customer gửi thông điệp trả lời đề nghị trước khi gửi thông điệp yêu cầu. o Kết quả: Hình 6.10: Agent – wrongTest1 o Nhận xét: Agent ShoppingCart vẫn xử lý yêu cầu từ phía Customer nhưng có hai dòng thông báo lỗi hiện lên báo sai đặc tả. Như vậy mã 70 aspect kiểm chứng đã phát hiện ra lỗi sai đặc tả và thông báo cho người dùng. - WrongTest2: Agent ShoppingCart gửi cả thông điệp chấp nhận đặt hàng và từ chối đặt hàng khi Customer gửi một yêu cầu đặt hàng. o Kết quả: Hình 6.11: Agent – wrongTest2 o Nhận xét: Mã aspect kiểm chứng bắt được lỗi sai đặc tả giao thức trong thời gian chạy. 6.3 Kết luận Trong chương này, tôi đã trình bày cách cài đ ặt công cụ PVG dựa vào phương pháp “kiểm chứng đặc tả UML cho tác tử phần mềm”. Mã aspect được sinh ra từ công cụ PVG sẽ được đan vào mã ngu ồn của chương trình chính thông qua trình biên d ịch AspectJ để kiếm chứng giao thức đặc tả trong thời gian chạy. Bước đầu tiến hành kiểm chứng một số giao thức thực tế, tôi thấy mã aspect do công cụ PVG tạo ra đã đáp ứng được các yêu cầu kiểm chứng. 71 Chương 7. Kết luận 7.1 Kết luận về khóa luận Trong quá trình thực hiện khóa luận này, tôi đã tìm hiểu những kiến thức cơ bản về kiểm chứng phần mềm – là một trong những công đoạn vô cùng quan trọng giúp phát hiện và sửa lỗi phần mềm nhằm đảm bảo chất lượng phần mềm. Đồng thời tôi đã xây dựng phương pháp kiểm chứng phần mềm dựa trên AOP từ đó xây dựng công cụ tự động sinh mô-đun kiểm chứng. Trong phương pháp kiểm chứng các đặc tả giao thức cho ứng dụng, các mô-đun aspect chứa mã kiểm chứng sẽ là các mô-đun cắt ngang hệ thống và tách biệt so với chương trình ban đầu. Từ biểu đồ trạng thái hay biểu đồ trình tự UML, AUML đặc tả giao thức, tôi xuất biểu đồ này ra dạng tài liệu XMI. Tiếp đó tiến hành phân tích tài liệu XMI để xây dựng máy trạng thái mô tả giao thức đã đư ợc định nghĩa. Từ máy trạng thái xây dựng được, tôi tiến hành duyệt các trạng thái của máy trạng thái và dùng các thuật toán thao tác với xâu ký tự để sinh ra mã aspect chứa nội dung kiểm chứng. Áp dụng tư tưởng của phương pháp này, tôi đã phát tri ển thêm phương pháp kiểm chứng cho giao thức (AB)n. Để minh họa cho phương pháp “kiểm chứng đặc tả UML cho tác tử phần mềm”, tôi đã th ực nghiệm và xây dựng thành công khi cài đặt được công cụ Protocol Verification Generator tự động sinh mã aspect từ tài liệu XMI mô tả giao thức. Tuy nhiên, tôi cũng v ấp phải một số khó khăn trong quá trình xây d ựng phương pháp sinh mã aspect. Tác tử phần mềm có thể tự đưa ra các hành động tùy vào sự thay đổi của môi trường nên khi hệ thống chứa càng nhiều tác tử thì đặc tả giao thức sẽ càng khó khăn; mặt khác công cụ PVG chỉ sinh ra aspect từ những thông tin trong tài liệu XMI. Chính vì vậy việc xây dựng các mô-đun kiểm chứng chỉ từ tài liệu XMI biểu diễn giao thức nhiều khi là không đủ để sinh ra các mô-đun aspect kiểm chứng hoàn chỉnh. Hơn nữa, hệ thống đa tác tử, chứa càng nhiều tác tử thì việc đặc tả sẽ càng gặp khó khăn vì các dữ liệu trong biểu đồ UML đặc tả giao thức phải giống với trong mã nguồn của chương trình. Một khó khăn nữa là các biểu đồ UML rất hạn chế trong việc đặc tả các biểu thức điều kiện, chính vì vậy đôi khi ta chỉ kiểm chứng được một vài nhánh của chương trình mà không thể kiểm chứng được tất cả các nhánh. 72 7.2 Hướng phát triển trong tương lai Từ những vấn đề tồn tại của khóa luận này, trong tương lai tôi sẽ tiếp tục hướng nghiên cứu này nhằm xây dựng hoàn thiện công cụ Protocol Verification Generator để đáp ứng mọi yêu cầu. Hướng nghiên cứu gần nhất là phát triển công cụ để PVG để có giải quyết triệt để các giao thức ràng buộc phức tạp như tiền điều kiện, hậu điều kiện, giao thức AnBn, giao thức AnBf(n) trong đó f(n) là một hàm nào đó phụ thuộc vào n, giao thức AnBmCf(n,m) trong đó f(n,m) là hàm phụ thuộc vào n và m. Bên cạnh đó, tôi sẽ nghiên cứu và tìm ra các phương pháp sinh mã aspect ki ểm chứng không chỉ phụ thuộc vào tài liệu XMI mà còn phụ thuộc vào các ràng buộc điều kiện được đặc tả bởi các dạng dữ liệu khác nhằm tăng tính ứng dụng của công cụ PVG đối với công nghệ sản xuất phần mềm hiện nay. 73 Phụ lục Phụ lục A: Tài liệu XMI mô tả biểu đồ trạng thái UML <XMI xmi.version = "1.1" xmlns:UML="href://org.omg/UML/1.3" timestamp = "Mon May 18 17:41:3 2009"> StarUML.XMI-Addin 1.0 <UML:Model xmi.id="UMLModel.2" name="Dummy Model" visibility="public" isSpecification="false" namespace="UMLProject.1" isRoot="false" isLeaf="false" isAbstract="false"> <UML:Model xmi.id="UMLModel.3" name="Model1" visibility="public" isSpecification="false" namespace="UMLModel.2" isRoot="false" isLeaf="false" isAbstract="false"> <UML:StateMachine xmi.id="UMLStateMachine.4" name="StateMachine1" visibility="public" isSpecification="false" context="UMLModel.3"> <UML:CompositeState xmi.id="UMLCompositeState.5" name="TOP" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.4" isConcurrent="false"> <UML:Pseudostate xmi.id="UMLPseudostate.6" name="Initial" visibility="public" isSpecification="false" container="UMLCompositeState.5" outgoing="UMLTransition.11" kind="initial"/> <UML:SimpleState xmi.id="UMLCompositeState.7" name="State1" visibility="public" isSpecification="false" container="UMLCompositeState.5" outgoing="UMLTransition.12" incoming="UMLTransition.11"/> <UML:SimpleState xmi.id="UMLCompositeState.8" name="State2" visibility="public" isSpecification="false" container="UMLCompositeState.5" outgoing="UMLTransition.13" incoming="UMLTransition.12 UMLTransition.14"/> <UML:SimpleState xmi.id="UMLCompositeState.9" name="State3" visibility="public" isSpecification="false" container="UMLCompositeState.5" outgoing="UMLTransition.14 UMLTransition.15" incoming="UMLTransition.13"/> <UML:FinalState xmi.id="UMLFinalState.10" name="FinalState" visibility="public" isSpecification="false" container="UMLCompositeState.5" incoming="UMLTransition.15"/> 74 <UML:Transition xmi.id="UMLTransition.11" name="void init()" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.4" source="UMLPseudostate.6" target="UMLCompositeState.7"/> <UML:Transition xmi.id="UMLTransition.12" name="void start(int a, int b)" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.4" source="UMLCompositeState.7" target="UMLCompositeState.8"> <UML:BooleanExpression xmi.id="X.17" body="a >= b"/> <UML:Transition xmi.id="UMLTransition.13" name="void stop()" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.4" source="UMLCompositeState.8" target="UMLCompositeState.9"/> <UML:Transition xmi.id="UMLTransition.14" name="void start()" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.4" source="UMLCompositeState.9" target="UMLCompositeState.8"/> <UML:Transition xmi.id="UMLTransition.15" name="void destroy()" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.4" source="UMLCompositeState.9" target="UMLFinalState.10"/> 75 Phụ lục B: Tài liệu XMI mô tả biểu đồ trình tự UML <XMI xmi.version = "1.1" xmlns:UML="href://org.omg/UML/1.3" timestamp = "Mon May 18 17:44:49 2009"> StarUML.XMI-Addin 1.0 <UML:Model xmi.id="UMLModel.2" name="Model1" visibility="public" isSpecification="false" namespace="UMLProject.1" isRoot="false" isLeaf="false" isAbstract="false"> <UML:Collaboration xmi.id="UMLCollaborationInstanceSet.3" name="CollaborationInstanceSet1" visibility="public" isSpecification="false"> <UML:Interaction xmi.id="UMLInteractionInstanceSet.4" name="InteractionInstanceSet1" visibility="public" isSpecification="false" context="UMLCollaborationInstanceSet.3"> <UML:Message xmi.id="UMLStimulus.5" name="debit" visibility="public" isSpecification="false" sender="UMLObject.15" receiver="UMLObject.15" interaction="UMLInteractionInstanceSet.4"> <UML:CallAction xmi.id="UMLCallAction.6" name="" visibility="public" isSpecification="false" isAsynchronous="false" stimulus="UMLStimulus.5"/> <UML:Message xmi.id="UMLStimulus.7" name="getBalance" visibility="public" isSpecification="false" sender="UMLObject.15" receiver="UMLObject.16" interaction="UMLInteractionInstanceSet.4"> <UML:CallAction xmi.id="UMLCallAction.8" name="" visibility="public" isSpecification="false" isAsynchronous="false" stimulus="UMLStimulus.7"/> <UML:Message xmi.id="UMLStimulus.9" name="queryB" visibility="public" isSpecification="false" sender="UMLObject.16" receiver="UMLObject.16" interaction="UMLInteractionInstanceSet.4"> <UML:CallAction xmi.id="UMLCallAction.10" name="" visibility="public" isSpecification="false" isAsynchronous="false" stimulus="UMLStimulus.9"/> <UML:Message xmi.id="UMLStimulus.11" name="setBalance" visibility="public" isSpecification="false" sender="UMLObject.15" receiver="UMLObject.16" interaction="UMLInteractionInstanceSet.4"> 76 <UML:CallAction xmi.id="UMLCallAction.12" name="" visibility="public" isSpecification="false" isAsynchronous="false" stimulus="UMLStimulus.11"/> <UML:Message xmi.id="UMLStimulus.13" name="updateB" visibility="public" isSpecification="false" sender="UMLObject.16" receiver="UMLObject.16" interaction="UMLInteractionInstanceSet.4"> <UML:CallAction xmi.id="UMLCallAction.14" name="" visibility="public" isSpecification="false" isAsynchronous="false" stimulus="UMLStimulus.13"/> <UML:ClassifierRole xmi.id="UMLObject.15" name="Account" visibility="public" isSpecification="false" message2="UMLStimulus.5 UMLStimulus.7 UMLStimulus.11" message1="UMLStimulus.5" isRoot="false" isLeaf="false" isAbstract="false"> <UML:MultiplicityRange xmi.id="X.26" lower="1" upper="1" multiplicity="X.25"/> <UML:ClassifierRole xmi.id="UMLObject.16" name="DBManager" visibility="public" isSpecification="false" message2="UMLStimulus.9 UMLStimulus.13" message1="UMLStimulus.7 UMLStimulus.9 UMLStimulus.11 UMLStimulus.13" isRoot="false" isLeaf="false" isAbstract="false"> <UML:MultiplicityRange xmi.id="X.28" lower="1" upper="1" multiplicity="X.27"/> <UML:TaggedValue xmi.id="X.17" tag="return" value="void" modelElement="UMLStimulus.5"/> <UML:TaggedValue xmi.id="X.18" tag="return" value="int" modelElement="UMLStimulus.7"/> <UML:TaggedValue xmi.id="X.19" tag="arguments" value="String str" modelElement="UMLStimulus.9"/> <UML:TaggedValue xmi.id="X.20" tag="return" value="int" modelElement="UMLStimulus.9"/> 77 <UML:TaggedValue xmi.id="X.21" tag="arguments" value="int ba" modelElement="UMLStimulus.11"/> <UML:TaggedValue xmi.id="X.22" tag="return" value="void" modelElement="UMLStimulus.11"/> <UML:TaggedValue xmi.id="X.23" tag="arguments" value="String str" modelElement="UMLStimulus.13"/> <UML:TaggedValue xmi.id="X.24" tag="return" value="void" modelElement="UMLStimulus.13"/> 78 Phụ lục C: Agent Customer (Customer.java) import jade.core.Agent; import jade.core.AID; import jade.core.behaviours.Behaviour; import jade.lang.acl.ACLMessage; import jade.proto.AchieveREInitiator; import jade.domain.FIPANames; import java.util.Date; import java.util.Vector; public class Customer extends Agent { private int nResponders; static String str = ""; static String request = "true"; protected void setup() { // Read name of ShoppingCart as arguments final Object[] args = getArguments(); if(args != null && args.length > 0) { nResponders = args.length; System.out.println("Requesting dummy-action to "+nResponders+" responders."); // Gui REQUEST final ACLMessage msg = new ACLMessage(ACLMessage.REQUEST); msg.addReceiver(new AID((String) args[0], AID.ISLOCALNAME)); msg.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); // We want to receive a reply in 10 secs msg.setReplyByDate(new Date(System.currentTimeMillis() + 10000)); msg.setContent(request); //agreeSuggest(); sendRequest(); // AddBehavior addBehaviour(new AchieveREInitiator(this, msg) { protected void handleInform(ACLMessage inform) { String tmp = inform.getContent(); if(tmp.equals("suggest")) { //agreeSuggest(); refuseSuggest(); ACLMessage msg1 = new ACLMessage(ACLMessage.REQUEST); msg1.addReceiver(new AID((String) args[0], AID.ISLOCALNAME)); msg1.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); // We want to receive a reply in 10 secs msg1.setReplyByDate(new Date(System.currentTimeMillis() + 10000)); msg1.setContent(request); sendRequest(); addBehaviour(new AchieveREInitiator(myAgent, msg1) { protected void handleInform(ACLMessage inform) { 79 System.out.println("Agent "+inform.getSender().getName()+" successfully performed the requested action"); } protected void handleRefuse(ACLMessage refuse) { System.out.println("Agent "+refuse.getSender().getName()+" refused to perform the requested action"); } protected void handleFailure(ACLMessage failure) { if (failure.getSender().equals(myAgent.getAMS())) { // FAILURE notification from the JADE runtime: the receiver // does not exist System.out.println("Responder does not exist"); } else { System.out.println("Agent "+failure.getSender().getName()+" failed to perform the requested action"); } } protected void handleAllResultNotifications(Vector notifications) { if (notifications.size() < nResponders) { // Some responder didn't reply within the specified timeout System.out.println("Timeout expired: missing "+(nResponders - notifications.size())+" responses"); } } }); // AddBehavior } else { System.out.println("Agent "+inform.getSender().getName()+" dat hang thanh cong"); } } protected void handleRefuse(ACLMessage refuse) { System.out.println("Agent "+refuse.getSender().getName()+" khong chap nhan"); nResponders--; } protected void handleFailure(ACLMessage failure) { if (failure.getSender().equals(myAgent.getAMS())) { // FAILURE notification from the JADE runtime: the receiver // does not exist System.out.println("Agent Giohang khong hoat dong"); } else { System.out.println("Agent "+failure.getSender().getName()+" loi trong xu ly yeu cau"); } 80 } protected void handleAllResultNotifications(Vector notifications) { if (notifications.size() < nResponders) { // Some responder didn't reply within the specified timeout System.out.println("Timeout expired: missing "+(nResponders - notifications.size())+" responses"); } } }); } else { System.out.println("Khong co Agent ShoppingCart nao fuc vu"); } } static void sendRequest() { System.out.println("called sendRequest"); } static void agreeSuggest() { System.out.println("agreeSuggest"); request = "true"; } static void refuseSuggest() { System.out.println("refuseSuggest"); request = "false"; } } 81 Phụ lục D: Agent ShoppingCart (ShoppingCart.java) import jade.core.Agent; import jade.core.AID; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.AchieveREResponder; import jade.domain.FIPANames; import jade.domain.FIPAAgentManagement.NotUnderstoodException; import jade.domain.FIPAAgentManagement.RefuseException; import jade.domain.FIPAAgentManagement.FailureException; public class ShoppingCart extends Agent{ protected void setup() { System.out.println("Agent "+getLocalName()+" waiting for requests..."); MessageTemplate template = MessageTemplate.and( MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST), MessageTemplate.MatchPerformative(ACLMessage.REQUEST) ); addBehaviour(new AchieveREResponder(this, template) { protected ACLMessage prepareResponse(ACLMessage request) throws NotUnderstoodException, RefuseException { System.out.println("Agent "+getLocalName()+": REQUEST received from "+request.getSender().getName()+". Action is "+request.getContent()); String strReq = request.getContent(); if(strReq.equals("true")) { System.out.println("Agent "+getLocalName()+": Agree"); ACLMessage agree = request.createReply(); agree.setPerformative(ACLMessage.AGREE); agree.setContent("ok"); agreeRequest(); return agree; } else if (strReq.equals("suggest")) { System.out.println("Agent "+getLocalName()+": Agree"); ACLMessage agree = request.createReply(); agree.setPerformative(ACLMessage.AGREE); agree.setContent("suggest"); sendSuggest(); return agree; } else { refuseRequest(); System.out.println("Agent "+getLocalName()+": Refuse"); throw new RefuseException("check-failed"); } 82 } }); } static void sendSuggest() { System.out.println("ShoppingCart gui mot loi de nghi cho Customer"); } static void agreeRequest() { System.out.println("ShoppingCart Chap nhan yeu cau dat hang"); } static void refuseRequest() { System.out.println("ShoppingCart Tu choi dat hang"); }} 83 Phụ lục E: Aspect Template static String aspectTemplate = "\r\n" + " pointcut pc_$METHODNAME$($METHOD_ARG$): $ARGS$ call ($METHOD_RETURN$ $METHOD_NAME$($METHOD_ARG_TYPE$));\r\n" + " before($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " if ($PRE-CONDITIONS$){\r\n" + " System.out.print(\"Wrong at: \"+thisJoinPointStaticPart.getSignature());\r\n"+ " System.out.print(\" In file: \"+thisJoinPointStaticPart.getSourceLocation().getFileName());\r\n"+ " System.out.println(\" At line: \"+thisJoinPointStaticPart.getSourceLocation().getLine());\r\n"+ " }}\r\n" + " after($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " state = STATE_$METHOD_STATE_NAME$;\r\n" + " }\r\n"; static String strPointcutEntry = " pointcut pc_$METHODNAME$($METHOD_ARG$): $ARGS$ call ($METHOD_RETURN$ $METHOD_NAME$($METHOD_ARG_TYPE$)) ;\r\n" + " before($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " Object o = thisJoinPoint.getTarget();\r\n"+ " if (!sm.isBinded(o)) \r\n"+ " sm.newSharedState(o);\r\n"+ " }\r\n" + " after($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " String s = thisJoinPoint.getSignature().toString();\r\n" + " Object o = thisJoinPoint.getTarget();\r\n" + " log(\"change state: \" + sm.getSharedState(o).getState() + \" ---> \" + s); \r\n" + " sm.setSharedState(o, s);\r\n" + " }\r\n"; static String strPointcutExit = " pointcut pc_$METHODNAME$($METHOD_ARG$): $ARGS$ call ($METHOD_RETURN$ $METHOD_NAME$($METHOD_ARG_TYPE$));\r\n" + " before($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " Object o = thisJoinPoint.getTarget();\r\n" + " if (!sm.isBinded(o))\r\n"+ " sm.bind(o);\r\n" + " String s = thisJoinPoint.getSignature().toString();\r\n"+ " if (! isValidState(o, s)) {\r\n" + " log(\"Invalid change: \" + sm.getSharedState(o).getState() + \" ---> \" + s); \r\n" + " log(thisJoinPoint);\r\n" + " }\r\n"+ " }\r\n" + " after($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$){\r\n" + " String s = thisJoinPoint.getSignature().toString();\r\n" + " Object o = thisJoinPoint.getTarget();\r\n" + " log(\"change state: \" + sm.getSharedState(o).getState() + \" ---> \" + s); \r\n" + " if (exitSigs.contains(s))\r\n" + 84 " sm.reset(o);\r\n" + " }\r\n"; static String strPointcut = " pointcut pc_$METHODNAME$($METHOD_ARG$): $ARGS$ call ($METHOD_RETURN$ $METHOD_NAME$($METHOD_ARG_TYPE$));\r\n" + " before ($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " Object o = thisJoinPoint.getTarget();\r\n" + " if (!sm.isBinded(o))\r\n"+ " sm.bind(o);\r\n" + " String s = thisJoinPoint.getSignature().toString();\r\n"+ " if (! isValidState(o, s)) {\r\n" + " log(\"Invalid change: \" + sm.getSharedState(o).getState() + \" ---> \" + s); \r\n" + " log(thisJoinPoint);\r\n" + " }\r\n"+ " }\r\n" + " after($METHOD_ARG$): pc_$METHODNAME$($METHOD_ARG_NAME$) {\r\n" + " String s = thisJoinPoint.getSignature().toString();\r\n" + " Object o = thisJoinPoint.getTarget();\r\n" + " log(\"change state: \" + sm.getSharedState(o).getState() + \" ---> \" + s); \r\n" + " sm.setSharedState(o, s);\r\n" + " }\r\n"; Tài liệu tham khảo [1] [2] [3] [4] A. Colyer, A. Clement, G. Harley and M. Webster. Eclipse AspectJ: Aspect- Oriented Programming with AspectJ and the Eclipse AspectJ Development Tools. Addison Wesley Professional Publisher, 2004. [5] Anh-Hoang Truong, Thanh-Binh Trinh, Dang Van Hung, Viet-Ha Nguyen, Nguyen Thi Thu Trang, and Pham Dinh Hung. “Checking Interface Interaction Protocols Using Aspect-Oriented Programming”. SEFM' 08, Cape Town, South Africa, November 10-14, 2008. [6] David Hunter, Kurt Cagle, Chris Dix, Roger Kovack, Jonathan Pinnock, Jeff Rafter. Beginning XML, 4th edition. Wiley Publishing Inc, 2007. [7] J. D. Gradecki and N. Lesiecki. Mastering AspectJ Aspect-Oriented Programming in Java. Wiley Publishing Inc, 2003. [8] James Odell, H. Van Dyke Parunak, Bernhard Bauer. Representing Agent Interaction Protocols in UML , 1999. [9] James Odell, H. Van Dyke Parunak, Bernhard Bauer. Extending UML for Agents, 2000. [10] M. Wooldridge, N. Jennings, D. Kinny: The Gaia Methodology for Agent- Oriented Analysis and Design. Autonomous Agents and Multi-Agent Systems. 3 (3): (2000). [11] OMG. Unified Modeling Language. OMG Version 1.5 – 2003. [12] R. Laddad. AspectJ in Action Practical Aspect-Oriented Programming. Manning Publications Co., 2003. [13] R. S. Pressman. Software Engineering, A Practitioner’s Approach, 5th edition. Thomas Casson, 2001. [14] Timothy J. Grose, Gary C. Doney, Stephen A. Brodsky. Mastering XMI: Java Programming with XMI, XML, and UML. Wiley Publishing Inc,2002. [15] Y. Cheon and A. Perumandla. Specifying and checking method call sequences of Java programs. Software Quality Control, 15(1):7–25, 2007.

Các file đính kèm theo tài liệu này:

  • pdfLUẬN VĂN-KIỂM CHỨNG ĐẶT TẢ UML CHO TÁC TỬ PHẦN MỀM.pdf