Danh sách từ viết tắt và thuật ngữAPR Automated Program Repair - Sửa lỗi chương trình tự động AST Abstract Syntax Tree - Cây cú pháp trừu tượng FL Fault Localization - Xác định vị trí g
Trang 1TRƯỜNG ĐẠI HỌC CÔNG NGHỆ
Bùi Quang Cường
PHƯƠNG PHÁP TỰ ĐỘNG SỬA LỖI CHO CÁC CHƯƠNG TRÌNH JAVA
LUẬN VĂN THẠC SĨ Ngành: Khoa học máy tính
HÀ NỘI - 2020
Trang 2TRƯỜNG ĐẠI HỌC CÔNG NGHỆ
Bùi Quang Cường
PHƯƠNG PHÁP TỰ ĐỘNG SỬA LỖI
CHO CÁC CHƯƠNG TRÌNH JAVA
Ngành: Khoa học máy tính Chuyên ngành: Khoa học máy tính
Mã số: 60 48 01 01
LUẬN VĂN THẠC SĨ
NGƯỜI HƯỚNG DẪN KHOA HỌC: PGS TS Phạm Ngọc Hùng
HÀ NỘI - 2020
Trang 3UNIVERSITY OF ENGINEERING AND
TECHNOLOGY
Bui Quang Cuong
A METHOD FOR AUTOMATED REPAIR OF ERRORS FOR JAVA
PROGRAMS
MASTER THESIS OF COMPUTER SCIENCE
Major: Computer Science
Supervisor: Assoc Prof., Dr Pham Ngoc Hung
HANOI - 2020
Trang 4LỜI CAM ĐOAN
Tôi xin cam đoan rằng những nghiên cứu về phương pháp tự động sửa lỗi cho cácchương trình Java được trình bày trong luận văn này là của tôi và chưa từng đượcnộp như một báo cáo luận văn tại trường Đại học Công nghệ - ĐHQGHN hoặc bất kỳtrường đại học khác Những gì tôi viết ra không sao chép từ các tài liệu, không sửdụng các kết quả của người khác mà không trích dẫn cụ thể Tôi xin cam đoan công
cụ tự động sửa lỗi cho các chương trình Java tôi trình bày trong luận văn là do tôi tựphát triển, không sao chép mã nguồn của người khác Nếu sai tôi hoàn toàn chịutrách nhiệm theo quy định của trường Đại học Công nghệ - ĐHQGHN
Hà Nội, ngày 15 tháng 08 năm
2020Học viên cao học
Bùi Quang Cường
Trang 5kỹ thuật tập trung xử lý các lỗi hồi quy Tuy nhiên, các kỹ thuật chưa thực sự khai thácđầy đủ thông tin có sẵn trong lịch sử phát triển của các phần mềm (ví dụ: bản cậpnhật gây ra lỗi, v.v.) để sửa lỗi hồi quy Hơn nữa, những kỹ thuật này không công bốcông cụ cài đặt cho cộng đồng hoặc công cụ rất hạn chế và khó có thể sử dụng đểsửa lỗi trong thực tế Luận văn này nhằm mục đích đề xuất phương pháp sửa lỗi hồiquy cho các chương trình Java bằng cách khai thác và mở rộng những phát hiện gầnđây về lỗi hồi quy, ví dụ: mối tương quan giữa các bản cập nhật tạo ra lỗi và sửa lỗi.Luận văn cài đặt lại và cải tiến phương pháp sửa lỗi hồi quy tự động cho các chươngtrình C (Relifix) Từ đó, xây dựng một hệ thống có tên là LyFix, cho phép người dùngsửa lỗi hồi quy Java tự động bằng cách tận dụng các nguyên liệu sửa lỗi và các mẫusửa lỗi cụ thể học được từ lịch sử phát triển phần mềm Tám mẫu sửa lỗi hồi quy,thuật toán sửa lỗi đã được cài đặt lại dựa vào
ýtưởng của Relifix Ngoài ra, luận văn cài đặt thêm ba mẫu sửa lỗi hồi quy mới choJava Luận văn cũng thực hiện thực nghiệm để so sánh khả năng sửa lỗi của LyFixđối với jRelifix (bản cài đặt Relifix cho Java) và các công cụ sửa lỗi tự động tốtnhất hiện nay (jGenProg, jMutRepair, TBar) trên tập dữ liệu 51 lỗi hồi quy thực tếcủa các hệ thống phần mềm Java mã nguồn mở Kết quả cho thấy LyFix có thểsinh ra bản vá thành công cho 56.8% lỗi có trong tập dữ liệu và tỉ lệ số bản váchính xác là 79.3% trong khi các công cụ khác sửa lỗi tốt nhất (TBar) với kết quảsinh được bản vá 33.3% lỗi và tỉ lệ bản vá đúng là 41.1%
Từ khóa: tự động sửa lỗi chương trình, lỗi hồi quy, lịch sử phát triển phần mềm
Trang 6LỜI CẢM ƠN
Đầu tiên và quan trọng nhất, tôi xin gửi lời cảm ơn trân trọng và sâu sắc tớiPGS TS Phạm Ngọc Hùng - người Thầy giáo đã trực tiếp hướng dẫn tận tình vàđóng góp những ý kiến quý báu trong quá trình tôi học tập, nghiên cứu và cả kinhnghiệm cuộc sống từ những năm tháng tôi còn là sinh viên tại trường Đại họcCông nghệ cho đến nay Thầy đã không ngần ngại cho phép và hỗ trợ tôi tự lựachọn đề tài để thực hiện luận văn này Tôi xin được gửi lời cảm ơn chân thành tới
TS Bách Lê, TS Lê Quang Lộc, và PGS TS Corina Pasareanu đã hướng dẫn và
hỗ trợ tôi rất nhiệt tình trong quá trình thực hiện luận văn này Các anh và cô luônđộng viên tôi và đưa ra những câu trả lời và gợi ý ngay lập tức mỗi khi tôi gặp khókhăn Các anh và cô cũng chia sẻ rất nhiều kinh nghiệm quý báu trong nghiên cứu
và cuộc sống và tôi đã học được nhiều điều từ các anh Xin được cảm ơn ban tổchức chương trình Google Summer of Code 2020 và Java PathFinder Team đãcho phép tài trợ kinh phí để tôi thực hiện đề tài trong luận văn này Công trình nàycũng được tài trợ một phần từ đề tài KHCN cấp ĐHQGHN, Mã số đề tài:QG.19.24 Cuối cùng, tôi xin được cảm ơn những lời động viên từ gia đình, ngườithân, bạn bè để giúp tôi luôn vững bước trong con đường tương lai
Trang 7Mục lục
1 Giới thiệu
1.1 Mở đầu 1.2 Đóng góp 1.3 Bố cục luận văn
2 Kiến thức nền tảng
2.1 Kiểm thử hồi quy và lỗi hồi quy 2.2 Sửa lỗi chương trình tự động 2.2.1
2.2.2
3 Phương pháp sửa tự động lỗi hồi quy
3.1 Tổng quan phương pháp 3.2 Xác định bản cập nhật gây ra lỗi
3.4 Các mẫu sửa lỗi 3.5 Xác định vị trí gây lỗi
Trang 84 Cài đặt công cụ và thực nghiệm
4.2.14.2.2
Tài liệu tham khảo
Trang 9Danh sách hình vẽ
2.1 Các chiến lược kiểm thử hồi quy
2.3 Số lượng công bố mỗi năm về APR từ 1996 - 2019
2.5 Tổng quan về các kỹ thuật sửa lỗi [14] 3.1 Tổng quan phương pháp sửa tự động lỗi hồi quy 3.2 Các bản cập nhật gây ra lỗi và sửa lỗi của Closure 31 [21]
3.3 Ví dụ minh họa tính độ đo giữa nguyên liệu sửa lỗi và câu lệnh nghi
ngờ lỗi 4.1 Kiến trúc công cụ sửa lỗi tự động LyFix
Trang 10Danh sách bảng
3.1 Nguyên liệu sửa lỗi và mẫu sửa lỗi sử dụng 3.2 Các mẫu sửa lỗi đã cài đặt 4.1 Thống kê các chỉ số của bộ dữ liệu lỗi hồi quy
4.3 Kết quả sửa lỗi trên tập dữ liệu lỗi hồi quy
Trang 11Danh sách từ viết tắt và thuật ngữ
APR Automated Program Repair - Sửa lỗi chương trình tự động
AST Abstract Syntax Tree - Cây cú pháp trừu tượng
FL Fault Localization - Xác định vị trí gây lỗi SUT
System Under Test - Hệ thống được kiểm thử
RTS Regression Test Selection - Lựa chọn ca kiểm thử hồi quy
TSM Test Suite Minimization - Giảm thiểu bộ ca kiểm thử
TCP Test Case Prioritization - Ưu tiên ca kiểm thử
BWTC Bug-witnessing Test Case - Ca kiểm thử phát hiện lỗi
BIC Bug-inducing Commit - Bản cập nhật gây lỗi
BFC Bug-fixing Commit - Bản cập nhật sửa lỗi
RT Repair Templates - Các mẫu sửa lỗi, mỗi mẫu thực hiện một
tập các hành động thay đổi mã nguồn để sửa lỗi
FI Fix Ingredients - Các nguyên liệu sửa lỗi, là những thành phần
mã nguồn có thể sử dụng làm tham số cho các mẫu sửa lỗi
Trang 12Chương 1
Giới thiệu
Các hệ thống phần mềm phát triển và tiến hóa không ngừng như một lẽ tự nhiên
để bắt kịp nhu cầu thay đổi liên tục từ phía khách hàng và thị trường Quá trìnhphát triển phần mềm là một quá trình gia tăng, thường mang theo các tính năngmới được cài đặt để đáp ứng các yêu cầu thay đổi của người dùng Tuy nhiên,những tính năng được thêm mới này có thể làm hỏng các chức năng hiện tại của
hệ thống phần mềm và do đó gây ra lỗi mới Những lỗi này thường được gọi là lỗi
hồi quy Lỗi hồi quy rất phổ biến trong các hệ thống phần mềm hiện nay và vẫn
đang là một thách thức lớn trong ngành công nghiệp phát triển phần mềm [35, 11]
Xác định và sửa lỗi hồi quy là một hoạt động bắt buộc trong các vòng lặp bảo trìphần mềm [39] Những nghiên cứu từ trước đến nay tập trung chủ yếu vào việc
hỗ trợ phát hiện và xác định lỗi hồi quy [39, 52, 26, 22] Trong khi đó, sửa lỗi hồiquy vẫn đang phụ thuộc lớn vào con người để gỡ và sửa lỗi một cách thủ công,khiến công việc này tiêu tốn thời gian và rủi ro Ví dụ, người ta đã ước tính rằngcác lập trình viên cần tới 8,5 năm để sửa một lỗi hồi quy [4]
Sửa lỗi tự động (Automated Program Repair - APR), bao gồm các pha xác định vịtrí gây ra lỗi và sửa lỗi mới xuất hiện gần đây để giúp giải quyết vấn đề này APR tậptrung vào việc tự động quá trình gỡ lỗi phần mềm, từ đó giúp giảm bớt hoặc thậm chíloại bỏ sự can thiệp của con người vào quá trình sửa lỗi Các nghiên cứu
Trang 13về APR gần đây đã đạt được một số thành công đáng kể và đóng góp cho ngànhnhiều kỹ thuật sửa lỗi tốt [45, 17, 12] Facebook gần đây đã công bố công cụ sửa lỗi
tự động lần đầu tiên, được sử dụng rộng để sửa lỗi cho toàn bộ hệ thống mã nguồnlõi mà Facebook đang vận hành [2] Điều này khẳng định APR đang là một hướngnghiên cứu mang lại nhiều đóng góp lớn cho lĩnh vực phát triển phần mềm
Mặc dù với sự phát triển mạnh mẽ gần đây, chỉ có một số kỹ thuật APR tập trungcho việc sửa lỗi hồi quy [33, 42] Tuy nhiên, những kỹ thuật này hiện tại vẫn chưa khaithác đầy đủ thông tin trong lịch sử phát triển của hệ thống (ví dụ: thông tin thay đổitrong những bản cập nhật gây ra lỗi) để phục vụ cho việc sửa lỗi Hơn nữa, nhữngphương pháp sửa lỗi này không cung cấp công khai công cụ cài đặt kèm theo hoặccông cụ rất hạn chế và khó có thể áp dụng để sửa lỗi trong các dự án thực tế Luậnvăn này hướng tới việc áp dụng sửa lỗi hồi quy tự động cho các chương trình Javabằng cách cài đặt và mở rộng các phương pháp sửa lỗi và các phát hiện gần đây vềlỗi hồi quy (ví dụ: phương pháp sửa lỗi hồi quy tự động cho các chương trình C [42],
sự tương quan giữa các bản cập nhật gây ra lỗi và sửa lỗi [46]) Luận văn tập trungvào việc sửa lỗi cho các chương trình Java bởi vì nó là một trong những ngôn ngữ lậptrình phổ biến nhất cho đến hiện nay.1 Luận văn cũng đặt mục tiêu xây dựng mộtcông cụ kèm theo, có tên LyFix, cho phép người dùng sửa lỗi hồi quy Java tự động vàcông bố nó như một phần mềm mã nguồn mở để cộng đồng có thể sử dụng Khác vớicác kỹ thuật APR truyền thống, LyFix sử dụng các nguyên liệu sửa lỗi và những mẫusửa lỗi cụ thể học từ lịch sử phát triển của các hệ thống phần mềm để đạt kết quảsửa lỗi tốt hơn cho các lỗi hồi quy
Luận văn phân tích bán tự động 3483 lỗi của hai bộ dữ liệu lỗi chuẩn BugSwarm2
và Bears3, từ đó thu thập được 51 lỗi hồi quy BugSwarm bao gồm 3232 lỗi đượcthu thập tự động dựa trên lịch sử tích hợp liên tục (TravisCI) của các ứng
1 http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
2
http://www.bugswarm.org/releases/#v113
3 http://bears-bugs.github.io/bears-benchmark
Trang 14dụng mã nguồn mở Bears bao gồm 251 lỗi được thu thập thủ công từ các ứng dụng mã nguồn mở với mục đích phục vụ cho các công cụ APR.
Luận văn cài đặt và công bố miễn phí công cụ kèm theo LyFix4, bao gồm:
– Đề xuất và cài đặt công thức xác định vị trí gây lỗi phù hợp cho đối
tượng là lỗi hồi quy
– Cài đặt lại tám mẫu sửa lỗi dựa trên tư tưởng sửa lỗi hồi quy cho
chương trình C ở [42]
– Đề xuất và cài đặt ba mẫu sửa lỗi hồi quy mới cho Java (mở rộng dựa
trên [36] và học từ bộ dữ liệu 51 lỗi quy đã thu thập)
– Đề xuất và cài đặt thuật toán cải tiến từ thuật toán sửa lỗi của [42] để sinh được nhiều bản vá hơn và các bản vá có chất lượng tốt hơn
Luận văn tiến hành thực nghiệm đánh giá khả năng sửa lỗi của LyFix so với jRelifix (là công cụ sửa lỗi phiên bản Java mà luận văn đã cài đặt lại giống với phương pháp sửa lỗi đề xuất trong [42]), jGenProg, jMutRepair và TBar trên tập dữ liệu 51 lỗi hồi quy Đây là những lỗi hồi quy thực tế từ những hệ thống phần mềm mã nguồn mở được phát triển và kiểm thử tốt
trí gây ra lỗi, các mẫu sửa lỗi và thuật toán sửa lỗi Chương 4 mô tả về kiến trúc
và cài đặt công cụ, các kết quả thực nghiệm đánh giá về khả năng sửa lỗi hồi quy
của phương pháp đề xuất được tiến hành và bàn luận Cuối cùng, Chương 5 kết
luận lại toàn bộ công việc luận văn đã thực hiện, kèm theo các công việc tiếp theo
có thể thực hiện để cải tiến và mở rộng công cụ
4 https://github.com/bqcuong/lyfix
Trang 15Chương 2
Kiến thức nền tảng
Chương này cung cấp các kiến thức nền tảng cho luận văn Đầu tiên, kiến thứckiểm thử hồi quy sẽ được giới thiệu một cách tổng quan Tiếp theo, kiến thức vềsửa lỗi chương trình tự động sẽ được trình bày, bao gồm: tổng quan, xác định vịtrí gây ra lỗi, và các phương pháp sửa lỗi tự động phổ biến hiện nay
Các hệ thống phần mềm thay đổi không ngừng theo thời gian Khi có một thay đổimới được thêm vào mã nguồn, thay đổi này có thể phá hỏng các chức năng kháccủa chương trình mà trước đó hoạt động bình thường Kiểm thử hồi quy(regression testing) là một kỹ thuật được sử dụng để phát hiện các lỗi khi chươngtrình thay đổi Kiểm thử hồi quy có thể áp dụng ở tất các mức kiểm thử: đơn vị,tích hợp, hệ thống, và chấp nhận [16] Lỗi được phát hiện nhờ vào kiểm thử hồiquy gọi là lỗi hồi quy Lỗi hồi quy được chia thành ba loại1:
Local: Thay đổi mới gây ra lỗi, làm các chức năng tồn tại từ trước không
hoạt động đúng như mong muốn nữa Cách sửa là khôi phục lại phần mã
nguồn gây ra lỗi này
1 http://www.onestoptesting.com/regression-testing/types.asp
Trang 16Unmasking: Thay đổi mới khiến luồng thực thi chương trình đi vào những
câu lệnh gây ra những lỗi đã có từ trước Cách sửa là thêm hoặc cập nhật lại
các câu lệnh điều kiện để giúp luồng thực thi chương trình không còn đi vào các câu lệnh gây lỗi nữa
Remote: Những thay đổi mới tạo ra các lỗi ở những phần mã nguồn khác
trong chương trình Để sửa những lỗi này, ta buộc phải cập nhật lại mã
nguồn ở những vị trí có lỗi cho phù hợp với thay đổi hoặc ta cần phải tạo ra các câu lệnh điều kiện để luồng thực thi chương trình không đi vào những câu lệnh gây lỗi đối với một số trạng thái nhất định
Kiến thức về thông tin, tính chất của các loại lỗi hồi quy sẽ giúp luận văn nàyphát triển kỹ thuật xác định vị trí lỗi, lựa chọn được các nguyên liệu sửa lỗi phùhợp, và thiết kế được các mẫu sửa lỗi tốt hơn Kiến thức về các kỹ thuật kiểm thửhồi quy giúp luận văn thiết kế thuật toán, lựa chọn bộ ca kiểm thử rút gọn để tiếtkiệm thời gian thẩm định bản vá
H ÌNH 2.1: Các chiến lược kiểm thử hồi quy
Hình 2.1 mô tả các chiến lược phổ biến được sử dụng để thực hiện kiểm thử hồiquy hiện nay Trong thực tế, người ta chỉ thực thi một phần của bộ ca kiểm thử đểthực hiện kiểm thử hồi quy Thử thách lớn nhất là cần thực thi lựa chọn đúng những
ca kiểm thử có thể giúp đánh giá tốt nhất cho những phần mã nguồn thay đổi Thựcthi lại toàn bộ ca kiểm thử (Retest All) chỉ khả thi cho những dự án nhỏ Trong những
dự án có quy mô lớn, việc thực thi lại toàn bộ ca kiểm thử hầu như là
Trang 17điều không thể bởi vì nó tốn rất nhiều thời gian và có thể làm chậm quá trình pháthành sản phẩm tới khách hàng.
Giảm thiểu bộ ca kiểm thử (Test Suite Minimization - TSM): Trong những hệ
thống phần mềm quy mô lớn, bộ ca kiểm thử cho những hệ thống này thường rất
đồ sộ, và luôn được cập nhật thêm mới các ca kiểm thử mỗi khi trải qua một bảnphát triển mới Việc thêm các ca kiểm thử mới có thể khiến những ca kiểm thửkhác trở nên dư thừa bởi vì chức năng ca kiểm thử cũ có thể cũng đã được kiểmtra bởi những ca kiểm thử mới Loại bỏ những ca kiểm thử dư thừa này khônglàm ảnh hướng tới độ phủ của bộ kiểm thử [41] Các kỹ thuật TSM nhắm tới mụctiêu xác định và loại bỏ những ca kiểm thử dư thừa này ra khỏi bộ ca kiểm thử.Một số nghiên cứu đã được đề xuất có kết quả tốt như là [25, 47, 15]
Lựa chọn ca kiểm thử (Test Case Selection): Có tên gọi khác là Regression
Test Selection - RTS Các kỹ thuật RTS giống với các kỹ thuật TSM là đều lựa
chọn một tập ca kiểm thử con và chỉ thực hiện kiểm thử hồi quy trên tập đó Điểm
khác biệt chính giữa hai loại kỹ thuật này là RTS lựa chọn ca kiểm thư dựa vàocác thay đổi của hệ thống được kiểm thử (System Under Test - SUT) còn TSM thìkhông Các kỹ thuật TSM thường lựa chọn ca kiểm thử dựa vào các chỉ số như độphủ kiểm thử được đo từ một phiên bản nhất định của SUT Ngược lại, RTS lựachọn các ca kiểm thử dựa trên sự liên quan của chúng so với thay đổi giữa haiphiên bản của nguồn của SUT Có nhiều nghiên cứu tập trung đã vào đề xuất các
kỹ thuật RTS [39], [52], [53]
Ưu tiên ca kiểm thử (Test Case Prioritization - TCP): Các kỹ thuật TCP
không lựa chọn một tập các ca kiểm thử còn mà tập trung vào việc sắp xếp độ ưu
tiên thực thi của các kiểm thử theo một thứ tự dựa vào một số tiêu chí nào đó để
có thể tìm được lỗi nhanh nhất Điều này giúp cho các kiểm thử viên có thể tối đa
tỷ lệ có thể tìm được lỗi sớm của bộ kiểm thử Các kỹ thuật TCP có thể chia làm
ba nhóm chính dựa trên các mức điều khiển, câu lệnh, và hàm của chương trình
[38] Một số nghiên cứu đề xuất các kỹ thuật TCP là [26], [22], [23]
Trang 182.2 Sửa lỗi chương trình tự động
Sửa lỗi chương trình là một trong các bước của công việc gỡ lỗi chương trình cũng
như vòng đời của lỗi chương trình, bao gồm: Nhận diện lỗi - Nhận diện sự tồn tại của
lỗi trong chương trình, quan sát các dấu hiện của lỗi để phục vụ cho các bước sau;
Xác định vị trí gây ra lỗi - Thường là bước khó nhất, mục tiêu là để xác định xem phần
nào của chương trình gây ra lỗi, cụ thể nhất là ở dòng nào; Sửa lỗi - Xác định cách
giải quyết lỗi như thế nào, sau đó đề xuất bản vá và thẩm định lại bản vá
H ÌNH 2.2: Các bước tiêu chuẩn trong các kỹ thuật APR hiện nay [27]
Sửa lỗi chương trình tự động nhắm tới mục đích tự động hóa quá trình gỡ lỗi,giảm nhu cầu về sự can thiệp của con người trong công việc này Các kỹ thuậtAPR hiện tại thường gồm ba bước chính để thực hiện nhiệm vụ sửa lỗi một hoànchỉnh như mô tả ở Hình 2.2: Xác định vị trí gây ra lỗi ! Sinh và đề xuất bản vá !Thẩm định bản vá Tương tự ở quá trình gỡ lỗi tự nhiên của con người, mô-đunxác định vị trí gây lỗi ở APR cũng nhằm mục đích xác định các phần mã nguồnnghi ngờ gây ra lỗi (ở mức dòng, phương thức, hoặc tệp) Mô-đun sinh bản vá sẽ
cố gắng sửa lỗi bằng cách tạo ra nhiều bản vá ứng cử viên nhờ việc biến đổi mãnguồn có lỗi theo phương pháp đề xuất (cú pháp, ngữ nghĩa, hướng dữ liệu, v.v.).Những bản vá ứng cử viên này sẽ được mô-đun thẩm định bản vá kiểm tra xem
có thực sự sửa lỗi thành công hay không thông qua việc thực hiện đánh giáchương trình đã được vá lỗi theo một đặc tả cho trước (bộ ca kiểm thử, đặc tảhình thức, v.v.) Kết quả cuối cùng sẽ là một danh sách bản vá lỗi được đề xuấtcho người dùng mà có thể sử dụng để sửa lỗi chương trình ban đầu
Từ đầu những năm 2000, đã có rất nhiều nghiên cứu được thực hiện nhằm đềxuất các giải pháp phát hiện lỗi trong phần mềm [3, 6, 40] và xác định vị trí gây ra
Trang 19lỗi [37, 18, 19] Các nghiên cứu cho việc tự động sửa lỗi xuất hiện theo sau vớimột số lượng bài báo còn hạn chế Tuy nhiên, kể từ khi Weimer và cộng sự giớithiệu một phương pháp sửa lỗi mới dựa trên tư tưởng lập trình di truyền [45] vàonăm 2009, APR đã phát triển rất mạnh mẽ và trở thành một hướng nghiên cứuhẹp thiết yếu đối với lĩnh vực công nghệ phần mềm Điều này dễ dàng được nhậnthấy ở biểu đồ thống kế số lượng công bố các nghiên cứu về APR trong giai đoạn
1996 - 2019 trong Hình 2.32 Số lượng các công bố nghiên cứu về APR mỗi nămtrước năm 2009 là dưới 5 công bố và sau năm 2009 không ngừng tăng mạnh đạt
số lượng xấp xỉ 50 công bố ở các năm gần đây như năm 2018, 2019
H ÌNH 2.3: Số lượng công bố mỗi năm về APR từ 1996 - 2019
2 http://program-repair.org/statistics.html
Trang 202.2.1 Xác định vị trí gây ra lỗi
Nhìn vào sơ đồ ở Hình 2.2, ta có thể thấy rằng xác định vị trí gây lỗi là bước đầutiên trong các bước xử lý của bất kỳ phương pháp APR nào Xác định vị trí gây lỗiđược sử dụng để xác định những vị trí mã nguồn nghi ngờ gây ra lỗi Những vị trí
mã nguồn này sẽ được đưa vào các hệ thống APR để tập trung sửa lỗi tại đó Ta
sẽ tìm hiểu tổng quan các kỹ thuật xác định vị trí gây lỗi hiện nay, và sau đó tậptrung vào kỹ thuật xác định vị trí gây lỗi dựa trên phổ (spectrum-based FaultLocalization) - là chiến lược xác định lỗi được sử dụng phổ biến nhất trong các kỹthuật APR và trong luận văn này
Các kỹ thuật xác định vị trí gây lỗi truyền thống rất trực quan và đơn giản, bất
cứ người lập trình nào cũng có thể sử dụng Ta có thể nhắc tới bốn phương phápsau đây [48]:
Hệ thống log: Sử dụng các câu lệnh dùng để in các giá trị trong chương
trình (ví dụ: câu lệnh System.out.println()) Đây là một cách cực kỳ đơn giản
và hữu hiệu để theo dõi thông tin về trạng thái của chương trình Khi mà pháthiện có lỗi trong chương trình, nhà phát triển có thể điều tra log của chương trình để tìm ra vị trí lỗi xuất phát từ đâu
Assertions: Là các câu lệnh do người phát triển thêm vào để đảm bảo các giá trị trạng thái của chương trình đúng với mong muốn tại thời điểm chèn assertion
(ví dụ: assertEquals(5, arr.length)) Chương trình sẽ dừng lại ngay lập tức nếu như một trong các câu lệnh assertion đánh giá sai Từ đó nhà phát triển có thể biết được lỗi bắt đầu ở câu lệnh cuối cùng thay đổi giá trị của biến được kiểm tra trong câu lệnh assertion (như ví dụ trên, biến này là arr.length)
Breakpoints: Các trình gỡ lỗi sẽ cho phép người đặt các Breakpoint này.
Break-point được sử dụng để dừng chương trình khi luồng thực thi đi đến mộtđiểm mong muốn, và nó cho phép nhà phát triển có thể theo dõi được trạng tháihiện tại của chương trình Thậm chí nhà phát triển có thể thay đổi được giá trịcác biến, thêm các câu lệnh mới ngay sau điểm Breakpoint để đánh giá và tìm
Trang 21hiểu thêm thông tin về lỗi để xác định vị trí gây ra lỗi Một số trình gỡ lỗi hỗ trợ các tính năng này là GNU GDB3, Microsoft Visual Studio Debugger4.
Profiling: Là một phương pháp phân tích các chỉ số trong lúc chạy chương trình
như mức sử dụng bộ nhớ, tốc độ thực thi, thường được sử dụng để đánh giá vàtối ưu chương trình Tuy nhiên, phương pháp này có thể được sử dụng để tìm
ra một số lỗi chương như: Xác định lỗi rò rỉ bộ nhớ, Phát hiện số lầnthực thi không mong muốn của một hàm, v.v Một số công cụ tiêu biểu có thểnói đến là Valgrind5, VisualVM6
Các kỹ thuật xác định vị trí gây lỗi truyền thống thường được thực hiện mộtcách thủ công hoặc bán tự động Chính vì vậy, các kỹ thuật xác định vị trí gây lỗinâng cao ra đời, nhằm giảm thiểu tối đa sự can thiệp của con người vào quá trìnhxác định vị trí lỗi Các kỹ thuật xác định vị trí gây lỗi nâng cao phổ biến hiện này cóthể chia làm tám loại chính [48]: Dựa trên lát cắt (slide-based), Dựa trên mật đổphổ chương trình (spectrum-based), Dựa trên xác suất (statistics-based), Dựatrên trạng thái chương trình (state-based), Dựa trên học máy (machine learning-based), Dựa trên khai phá dữ liệu (data mining-based), Dựa trên mô hình (model-based), và Một số kỹ thuật khác [5, 7, 13]
H ÌNH 2.4: Tổng quan về xác định vị trí gây lỗi dựa trên phổ chương
Trang 22tin thực thi của chương trình theo một số khía cạnh nhất định Phổ chương trình
có thể dùng để theo dõi hành vi của chương trình, do đó nó có ích cho việc xácđịnh vị trí gây lỗi Khi một đường thực thi thất bại, những thông tin trên đườngthực thi đó có thể được sử dụng để xác định ra những dòng mã nguồn nghi ngờgây ra lỗi Ví dụ như thông tin về độ phủ mã nguồn (code coverage), hoặc ESHS(Executable Statement Hit Spectrum) có thể cho ta biết những câu lệnh nào đượcthực thi khi thực hiện đường thực thi thất bại Từ đó, giảm không gian tìm kiếmcho việc xác định các câu lệnh nghi ngờ gây ra lỗi
Có nhiều kỹ thuật xác định vị trí gây lỗi dựa trên phổ ra đời (chủ yếu dựa trênESHS), trong đó có một kỹ thuật dựa trên hệ số tương đồng nổi tiếng nhất làTarantula [20] Kỹ thuật này sử dụng thông tin về độ phủ các câu lệnh và kết quảcủa các lần thực thi bộ kiểm thử Từ đó, tính ra độ nghi ngờ gây lỗi cho các câulệnh trong chương trình theo Công thức 2.1 Giá trị của công thức này được tínhbằng tỉ lệ các ca kiểm thử failed đi qua câu lệnh s chia cho tổng tỉ lệ các ca kiểmfailed và passed đi qua câu lệnh s
Tarantula(s) =
Ochiai(s) =Trong đó: s là câu lệnh được tính độ nghi ngờ, f ailed(s) là số lượng ca kiểmthử thất bại có đường thực thi qua s, passed(s) là số lượng ca kiểm thử thất bại
có đường thực thi qua s, total f ailed là tổng số lượng ca kiểm thử thất bại, totalpassed là tổng số lượng ca kiểm thử thành công
Gần đây, kỹ thuật Ochiai [1] được đề xuất và thực nghiệm cho thấy Ochiai có kếtquả đánh giá tốt hơn so với Tarantula Độ nghi ngờ của các câu lệnh theo Ochiai
Trang 23được tính theo Công thức 2.2 Hình 2.4 mô tả tổng quan về kỹ thuật xác định vị7trí gây lỗi dựa trên phổ chương trình với độ nghi ngờ của các câu lệnh tính bằngcông thức Ochiai Với đầu vào là chương trình và bộ ca kiểm thử, thông tin về phổchương trình sẽ thu được nhờ thực thi tất cả ca kiểm thử (đường thực thi của cakiểm thử chạy qua những câu lệnh nào) Những thư viện hỗ trợ nhiệm vụ này cóthể là JaCoCo8, PIT9, v.v Tiếp đó, những thông tin về phổ này được sử dụng đểtính toán độ nghi ngờ cho từng câu lệnh dựa vào công thức đã đề xuất, giá trị độnghi ngờ thuộc đoạn [0.0, 1.0].
Hiện nay, các pnghiên cứu sửa lỗi tự động có thể chia thành ba loại chính: sửa lỗidựa trên phỏng đoán/cú pháp (heuristic-based), sửa lỗi dựa trên ràng buộc/ngữnghĩa (constraint-based), và sửa lỗi dựa trên học máy/dữ liệu (learning-based)
Các phương pháp sửa lỗi dựa trên phỏng đoán thường sử dụng chiến lược Sinh
và Thẩm định (Generate-and-Validate) Sau khi nhận kết quả các vị trí mã nguồn nghi
ngờ có lỗi từ mô-đun xác định vị trí gây lỗi, những phương pháp này đầu tiên sẽ sinh
ra một tập các biến đổi mã nguồn (bằng cách thêm, sửa, xóa các thành phần mãnguồn ở vị trí lỗi), gọi là không gian tìm kiếm Sau khi áp dụng những biến đối mãnguồn này vào chương trình có lỗi sẽ thu được một tập các bản vá ứng cử viên Quá
trình này gọi là Sinh Tiếp theo, quá trình Thẩm định sẽ thực thi các ca kiểm thử trên
các chương trình đã áp dụng các bản vá ứng cử viên và đếm số lượng ca kiểm thửthành công Nếu tất cả ca kiểm thử đều thành công, thì bản vá ứng cử viên đó đượccoi là một bản vá chính thức của chương trình có lỗi ban đầu Nhược điểm của các kỹthuật này là không gian tìm kiếm có thể vô cùng lớn bởi vì có vô số cách kết hợp củacác thành phần mã nguồn với nhau để tạo thành một bản vá Một số công cụ tiêu biểu
có thể kể đến khi nói đến những phương pháp này bao gồm GenProg [45], ssFix [49],
Trang 24H ÌNH 2.5: Tổng quan về các kỹ thuật sửa lỗi [14]
Các phương pháp sửa lỗi dựa trên ngữ nghĩa sử dụng một phương phápkhác so với chiến lược của những phương pháp dựa trên phỏng đoán Nhữngphương pháp này tập trung xây dựng ra hệ các ràng buộc để phục vụ cho việcsinh các bản vá Hệ các ràng buộc này thường mô tả về một phần mã nguồn (mãnguồn vá lỗi) mà có thể thỏa mãn được về kiểu, giá trị của biến hoặc hành vi được
mô tả trong các ràng buộc Phần mã nguồn vá lỗi này sẽ được coi như là một hàm
ẩn Ví dụ các phương pháp thực thi tượng trưng (symbolic execution) có thể tríchxuất ra được các thuộc tính của hàm ẩn này, sau đó các thuộc tính này sẽ đượctổng hợp thành hệ các ràng buộc Bằng cách sử dụng các bộ giải ràng buộc (ví dụZ3, CVC4, v.v.) hoặc các thuật toán tìm kiếm cao cấp, hệ các ràng buộc sẽ đượcgiải Phần mã nguồn vá lỗi sẽ được tổng hợp từ kết quả giải hệ các ràng buộcdựa trên các phương pháp tổng hợp chương trình (program synthesis) Nhữngphương pháp này thường sửa hiệu quả cho các lỗi liên quan đến các biểu thức
điều kiện ở câu lệnh if như sửa điều kiện sai, thêm điều kiện còn thiếu Một số
công cụ đại diện cho phương pháp này là SPS [31], Nopol [51], ACS [50], v.v
Trang 25Các phương pháp sửa lỗi dựa trên học máy thường sử dụng các kỹ thuật họcmáy tiên tiến, đặc biệt là học sâu để giúp tăng khả năng sửa lỗi Số lượng lớn dữliệu về các bản vá tự nhiên trong quá trình phát triển phần mềm của con người từcác hệ thống mã nguồn mở (ví dụ: SourceForge, Github, v.v.) đã cho phép các kỹthuật này phát triển mạnh mẽ Cho đến nay, các phương pháp sửa lỗi dựa trênhọc máy có ba loại chính:
Học tập các chương trình mã nguồn không có lỗi, từ đó đánh giá độ đúng đắn của các bản vá ứng cử viên sinh ra từ các phương pháp khác [30]
Học các mẫu sửa lỗi được tổng hợp từ các bản vá do con người thực hiện
để chuyển đổi từ mã nguồn có lỗi sang mã nguồn đúng [29]
Học cách cải tiến quá trình sửa lỗi và huấn luyện các mô hình sửa lỗi end, là các mô hình mà có thể dự đoán được code đúng từ code có lỗi mà không cần sử dụng bất cứ thông tin về ngữ cảnh nào (giống mô hình phục
end-to-vụ cho việc dịch ngôn ngữ tự động) [8]
Trong luận văn này, phương pháp sửa lỗi tự động dựa trên mẫu sửa lỗi(template-based repair) được sử dụng Phương pháp này có thể coi là một phươngpháp con của sửa lỗi dựa trên phỏng đoán Một mẫu sửa lỗi bao gồm thành phần
mã nguồn (ví dụ: câu lệnh, biểu thức, v.v.) và hành động sửa lỗi (ví dụ: thêm, sửa,xóa, v.v.) Để sửa lỗi với mẫu sửa lỗi, thì thuật toán sửa lỗi cần chọn ra đúng mẫuthích hợp để sửa được lỗi đó (ví dụ: đơn giản nhất là lựa chọn ngẫu nhiêu, hoặclựa chọn dựa vào thông tin ngữ cảnh của mã nguồn tại vị trí cần sửa) Các mẫusửa lỗi có thể được tạo ra bằng những cách sau:
Tổng hợp thủ công: Các nhà nghiên cứu phân tích các bản vá của con người
đã có và tự tạo và lựa chọn ra những mẫu sửa lỗi một cách thủ công
Theo xác suất: Sau khi thu thập được toàn bộ các mẫu sửa lỗi theo cách tự
động hoặc thủ công, tác giả chọn ra những mẫu có độ phổ biến nhất trong
tập dữ liệu để dùng cho kỹ thuật
Trang 26Khai phá: Các mẫu sửa lỗi được khai phá từ các nguồn dữ liệu (bản vá từ
các phần mềm mã nguồn mở, chính hệ thống hiện tại, thậm chí là từ câu trả
lời trên StackOverflow10) một cách tự động Luận văn này sử dụng các mẫu sửa lỗi đặc biệt cho lồi quy, được tạo ra theo cách thủ công và tập trung khai thác các thông tin trong bản cập nhật gây ra lỗi hồi quy
10 http://stackoverflow.com
Trang 27Chương 3
Phương pháp sửa tự động lỗi hồi quy
Chương này trình bày về các kỹ thuật được lựa chọn để phục vụ trong việc sửa tự
động lỗi hồi quy cho các chương trình Java Hình 3.1 biểu diễn tổng quan phương
pháp đề xuất Đầu tiên, bản cập nhật gây ra lỗi hồi quy cần được xác định Tiếp
theo, các thông tin mã nguồn thay đổi trong bản cập nhật này sẽ được thu thập và
biến đổi thành các nguyên liệu sửa lỗi Cuối cùng, những nguyên liệu sửa lỗi này
sẽ được sử dụng như đầu vào cho các mẫu sửa lỗi để sửa lỗi chương trình Luận
văn sử dụng các định nghĩa dưới đây để biểu diễn cho một số khái niệm sẽ được
trình bày trong chương này
Định nghĩa 3.1 (Ca kiểm thử phát hiện lỗi) Cho một phiên bản của chương trình
tồn tại lỗi hồi quy P7, một ca kiểm thử phát hiện lỗi (bug-witnessing test case) là ca
kiểm thử có kết quả passed trước khi lỗi xuất hiện và failed sau khi lỗi xuất hiện, kí
hiệu là TCbw TCbw có thể tồn tại trước hoặc sau phiên bản chương trình mà lỗi
xuất hiện lần đầu tiên Tập các ca kiểm thử phát hiện lỗi kí hiệu là TCBW
Định nghĩa 3.2 (Bản cập nhật gây lỗi) Cho một phiên bản chương trình không có lỗi P3,
một bản cập nhật gây lỗi (bug-inducing commit) là bản cập nhật làm cho phiên bản P3
chuyển thành phiên bản có lỗi hồi quy P7 Lỗi được phát hiện dựa vào TCBW
P
3
và 7 là liền kề nhau Kí hiệu là
P
Trang 28H ÌNH 3.1: Tổng quan phương pháp sửa tự động lỗi hồi quy
Định nghĩa 3.3 (Bản cập nhật sửa lỗi) Cho một phiên bản của chương trình tồn tại
lỗi hồi quy P7, một bản cập nhật sửa lỗi (bug-fixing commit) là bản cập nhật giúpphiên bản P7 chuyển thành phiên bản không có lỗi nữa P3, kí hiệu là P7!BFC P3
Thông tin về các phiên bản chương trình trong vòng đời của một lỗi hồi quy,
từ lúc lỗi xuất hiện đến lúc được sửa được thể hiện như dưới đây Giữa phiên bảnlỗi chương trình ngay sau bản cập nhật gây lỗi và phiên bản chương trình lỗi ngaytrước bản cập nhật sửa lỗi có thể tồn tại nhiều phiên bản khác Tuy nhiên, chúngkhông làm thay đổi kết quả của TCBW
Nhiệm vụ đầu tiên trong sửa lỗi hồi quy tự động là xác định được bản cập nhật gây
lỗi Đây là công việc rất quan trọng bởi vì hai lý do Thứ nhất, việc xác định được
Trang 29bản cập nhật gây lỗi cho ta biết được liệu rằng lỗi trong phiên bản chương trình
đang phân tích có thực sự là một lỗi hồi quy hay không Nếu ta tìm được một ca
khi thực137 hiện139thay đổi củaoptionsbản.foldConstants
là lỗi hồi quy và bản cập options nhật coalesceVariableNames làbảncậpnhậtgây = lỗi true Nếu ; không, ta có thể dừng
quá trình sửa lỗi bởi vì lỗi đang xét không phải là đối tượng của luận văn này Thứ hai, các 33mẫu
sửa lỗi src/com/google/javascript/jscomp/Compiler đượcđềxuấttrongluậnvănnàyđược java thiết kế đặc biệt
để có thể sử dụng các thông tin mã nguồn thay đổi trong bản cập nhật gây lỗi Do vậy, việc
1278 1284
Hình 3.2 mô tả các bản cập nhật gây ra lỗi và bản cập nhật sửa lỗi cho Clouse
Trang 301306 1307 1308 1309 1310 1446 1447
Trang 31Có nhiều nghiên cứu đã sử dụng SZZ (một thuật toán được sử dụng để xácđịnh các bạn cập nhật gây lỗi được đề xuất bởi Sliwerski và cộng sự [44]) để thuthập các bản cập nhật gây lỗi Tuy nhiên các nghiên cứu gần đây đã chỉ ra rằngSZZ có thể cho kết quả với độ chính xác thấp [9, 46] Lí do là bởi vì SZZ phụ thuộcvào một giả thuyết không được thẩm định đầy đủ Cụ thể, SZZ thường coi cácdòng mã nguồn được thay đổi ở bản cập nhật sửa lỗi là các câu lệnh gây ra lỗi, vàbản cập nhật gần nhất trước bản cập nhật sửa lỗi mà tạo ra thay đổi ở nhữngdòng mã nguồn đó sẽ là bản cập nhật gây lỗi Tuy nhiên, có thể có các bản cậpnhật không liên quan đến lỗi cũng tạo ra các thay đổi ở những dòng đó, mà nhữngbản cập nhật này nằm giữa bản cập nhật gây lỗi và bản cập nhật sửa lỗi.
Luận văn này đề xuất một phương pháp bán tự động để xác định bản cập nhậtgây lỗi với độ chính xác cao Sau khi nhận biết chương trình có lỗi (ví dụ tại phiên bản
P71 và thu thập được tập các ca kiểm thử TCBW ), để xác định được bản cập nhậtgây lỗi, ta có thể duyệt lùi lại lần lượt qua từng phiên bản chương trình bắt đầu từphiên bản hiện tại P71 cho đến khi gặp một phiên bản mà TCBW có kết quả passed,thì bản cập nhật tạo ra những thay đổi mã nguồn khiến kết quả TCBW thay đổi chính
là bản cập nhật gây lỗi Đây là một phương pháp đơn giản và trực quan, dễ thực hiện,tuy nhiên tồn tại những nhược điểm và khó khăn như sau
Thứ nhất, đối với các dự án đã được phát triển trong thời gian dài, có sốlượng bản ghi lịch sử các bản cập nhật lớn (từ 1000 - 10000 bản cập nhật), thìviệc duyệt qua từng bản cập nhật và thực thi các ca kiểm thử để kiểm tra lỗi trêncác phiên bản mã nguồn tiêu tốn một lượng thời gian khổng lồ và thậm chí khôngthực hiện được Giải pháp đưa ra là đầu tiên ta cần xác định một phiên bản mãnguồn bất kỳ (gọi là P31) ở quá khứ mà kết quả thực thi TCBW là passed bằngcách duyệt lùi nhanh (bước nhảy: 10, 20, 50, 100, v.v.) trong lịch sử bản cập nhật.Sau đấy sử dụng phương pháp tìm kiếm nhị phân để phát hiện ra bản cập nhậtlàm thay đổi kết quả của TCBW từ failed thành passed trong khoảng từ P31 đến
P71 Nếu ta không tìm được bất cứ một bản cập nhật nào khiến TCBW có kết quảpassed thì có nghĩa lỗi đang xét là lỗi tiến triển (progression bug) chứ không phảilỗi hồi quy hoặc do vấn đề sẽ được nhắc đến dưới đây
Không phải bao giờ các ca kiểm thử phát hiện lỗi TCBW cũng tồn tại trước khi
Trang 32lỗi hồi quy xuất hiện để ta có thể thực thi chúng một cách dễ dàng Trên thực tế, có rấtnhiều dự án mã nguồn mở mà luận văn này phân tích và thu thập lỗi hồi quy không có
TCBW từ trước Đây là sự thật bởi vì không phải bao giờ các lỗi hồi quy cũng đượccác nhà phát triển phát hiện nhờ bộ ca kiểm thử có sẵn Một số lỗi hồi quy được pháthiện dựa vào tri thức của nhà phát triển, và các ca kiểm thử được tạo ra sau khi sửaxong những lỗi này Do vậy, khi sử dụng TCBW để tìm lỗi ở các phiên bản cũ củachương trình, ta có thể được kết quả không chính xác Lí do thứ nhất là do một cakiểm thử có thể liên quan đến nhiều lỗi, khi ta cố gắng đưa mã nguồn ca kiểm thử này
để đánh giá lỗi cho các phiên bản cũ có thể cho kết quả failed bởi vì phần mã nguồnkiểm thử đó cũng được sử dụng để phát hiện cho một lỗi khác
M Ã NGUỒN 3.1: Ca kiểm thử liên quan đến nhiều lỗi trong Apache
a s s e r t E q u a l s ( Double valueOf ( Double MAX_VALUE) ,
NumberUtils createNumber ( " " + Double MAX_VALUE) , "
createNumber ( S t r i n g ) LANG 693 f a i l e d " ) ;
}
Mã nguồn 3.1 mô tả một ca kiểm thử có chứa mã nguồn phát hiện nhiều hơn mộtlỗi Giả định LANG-521 là lỗi mà ta đang muốn phân tích và xác định bản cập nhậtgây lỗi Khi ta sao chép phần mã nguồn của ca kiểm thử testCreateNumber về mộtphiên bản cũ hơn để kiểm tra trạng thái của lỗi LANG-521, có thể phần mã nguồnkiểm thử cho lỗi này cho kết quả passed tuy nhiên mã nguồn kiểm thử cho các lỗikhác như LANG-63, LANG-693 lại cho kết quả failed Kết quả cuối cùng của ca kiểmthử testCreateNumber là failed mặc dù phiên bản đó hoàn toàn không có
Trang 33sự tồn tại của lỗi LANG-521 Do vậy, kết quả xác định bản cập nhật gây lỗi không cònđược chính xác Một giải pháp đơn giản có thể được đề xuất để xử lý vấn đề này nhưsau Đầu tiên, ta thực thi phần mã nguồn của ca kiểm thử trên một phiên bản đượcxác định là có lỗi LANG-521 và xác định ra điểm có kết quả failed (câu lệnh assert)trong mã nguồn dựa vào log chương trình kiểm thử Sau đó, ta chỉ giữ lại câu lệnhassert này trong mã nguồn ca kiểm thử đó và loại bỏ những mã nguồn liên quan đếncác lỗi khác Phần mã nguồn khởi tạo giá trị các biến dữ liệu được sử dụng cho câulệnh assert cũng được giữ lại để đảm bảo ca kiểm thử có thể thực thi được.
Lí do thứ hai gây khó khăn cho việc thực thi các ca kiểm thử TCBW trên cácphiên bản mã nguồn cũ là thiếu phần mã nguồn hỗ trợ cho mã nguồn kiểm thử Ví
dụ ca kiểm thử được mô tả ở Mã nguồn 3.2 là ca kiểm thử phát hiện lỗi cho lỗiBears-41 trong bộ dữ liệu lỗi chuẩn Bears Mã nguồn ca kiểm thử này sử dụng lớpSerializationFeature, là một lớp được tạo ra ở bản cập nhật #9610aff Do vậy, takhông thể sử dụng mã nguồn ca kiểm thử này để kiểm tra lỗi ở các phiên bảntrước bản cập nhật #9610aff Đối với những trường hợp này, ta sẽ phải thực thi cakiểm thử phát hiện lỗi một cách thủ công và khoảng tìm kiếm cho bản cập nhậtgây lỗi là những bản cập nhật trước bản cập nhật #9610aff
M Ã NGUỒN 3.2: Mã nguồn ca kiểm thử phát hiện lỗi Bears-4
) ; S t r i n g s e r = mapper w r i t e V a l u e A s S t r i n g (new Something ( ) ) ;
mapper readValue ( ser , Something c l a s s ) ;
}
Xác định chính xác bản cập nhật gây lỗi cho các lỗi hồi quy là một công việckhó Luận văn đã đề xuất phương pháp để xác định bản cập nhật gây lỗi một cáchbán tự động (cần sự can thiệp con người ở những trường hợp mã nguồn ca kiểmthử phát hiện lỗi sử dụng các lớp hỗ trợ) Phương pháp này cho kết quả xác định
1 https://bears-bugs.github.io/bears-benchmark/!/bug/FasterXML-jackson-databind/Bears-4
Trang 34bản cập nhật gây lỗi chính xác hơn so với SZZ vì đánh giá cụ thể trạng thái lỗi hồi quycủa từng bản cập nhật với ca kiểm thử phát hiện lỗi chứ không coi các bản cập nhậtgần nhất thay đổi phần mã nguồn gây lỗi là bản cập nhật gây lỗi Phương pháp đềxuất không phải tự động hoàn toàn nên không được cài đặt tích hợp vào công cụchính của luận văn mà cài đặt thành một công cụ khác không được nhắc đến chínhthức Công cụ chính giả định đã xác định được chính xác bản cập nhật gây lỗi cho lỗihồi quy, và tập trung chính vào việc sinh ra các bản vá để sửa lỗi.
3.3 Thu thập thông tin mã nguồn thay đổi và nguyên
liệu sửa lỗi
Như mô tả ở Mục 3.2, thông tin thay đổi về các thành phần mã nguồn rất quantrọng trong việc lựa chọn mẫu sửa lỗi phù hợp, cung cấp nguyên liệu sửa lỗi chocác mẫu này, và thậm chí là giúp cải tiến độ chính xác của phương pháp FaultLocalization đối với các lỗi hồi quy Để thu thập các thông tin mã nguồn thay đổi, ta
có thể sử dụng công cụ mã nguồn GNU Diffutils để so sánh các tệp mã nguồn2text và tìm ra những dòng thay đổi Tuy nhiên công cụ này chỉ cung cấp thông tinthay đổi về nội dung theo dạng text dưới hai loại hành động thay đổi: thêm và xóa.Ngoài ra, việc ánh xạ các dòng mã nguồn thay đổi ở các phiên bản trước và saubản cập nhật gây lỗi có thể gặp khó khăn bởi vì có nhiều thay đổi khác không liênquan đến lỗi làm thay đổi vị trí câu lệnh ban đầu, từ đó khó có thể xác định đúngloại hành động thay đổi Do vậy, Gumtree Spoon AST Diff3 được sử dụng bởi vìthông tin mã nguồn thay đổi được biểu diễn dưới dạng cấu trúc dữ liệu AST, hỗ trợcung cấp thông tin vị trí thay đổi, và các loại hành động thay động đa dạng: thêm,cập nhật, xóa, di chuyển Cấu trúc dữ liệu AST này cho phép khai thác nhiềuthông tin về mã nguồn hơn định dạng text Ví dụ đối với câu lệnh khai báo biến int
a = f(x);, ta có thể dễ dàng thu được thông tin về tên biến (a), kiểu dữ liệu (int) vàgiá trị khởi tạo (f(x)) Những thông tin này giúp ta sinh các nguyên liệu sửa lỗi ởbước sau một cách dễ dàng hơn rất nhiều
2 https://www.gnu.org/software/diffutils
3
https://github.com/SpoonLabs/gumtree-spoon-ast-diff
Trang 35Các nguyên liệu sửa lỗi (fix ingredients) là các thành phần mã nguồn được sử
dụng cho các mẫu sửa lỗi Ví dụ mẫu sửa lỗi AddCon thì cần một biểu thức
boolean để thêm vào câu lệnh if tại vị trí gây ra lỗi Việc sửa lỗi có thành công haykhông phụ thuộc vào ba yếu tố: vị trí sửa, mẫu sửa lỗi và nguyên liệu sửa lỗi Vìvậy lựa chọn nguyên liệu sửa lỗi chính xác sẽ quyết định khả năng sửa lỗi của cácmẫu sửa lỗi nói riêng và của công cụ nói chung
Đối với các kỹ thuật sửa lỗi tự động Sinh và Thẩm định, các nguyên liệu sửa lỗi
thường được thu thập trong chính phiên bản chương trình hiện tại Tuy nhiên, đối vớicác lỗi hồi quy, thu thập nguyên liệu theo cách như vậy là chưa đủ để có thể sinhđược bản vá Các nguyên liệu sửa lỗi hồi quy thường nằm trong các thông tin thay đổi
ở bản cập nhật gây lỗi Nếu những nguyên liệu này chỉ được thêm, cập nhật hoặc dichuyển sang một vị trí khác; các kỹ thuật sửa lỗi hiện tại vẫn có thể thu thập và phục
vụ cho các mẫu sửa lỗi Tuy nhiên, nếu những nguyên liệu này biến mất khỏi mãnguồn sau khi thực hiện các hành động thay đổi ở bản cập nhật gây lỗi, thì nhữngcông cụ APR này không thể sửa lỗi vì không tìm được nguyên liệu phù hợp
B ẢNG 3.1: Nguyên liệu sửa lỗi và mẫu sửa lỗi sử dụng
Loại nguyên liệu Mẫu sửa lỗi
biểu thức boolean AddIf, AddCon, Negate
biến, biểu thức MI_AddArg, MI_UpdArg, MI_UpdObj
Phương pháp sửa lỗi hồi quy tự động đề xuất trong luận văn nhờ hiểu rõ tầmquan trọng của các nguyên liệu sửa lỗi được trích xuất từ thông tin thay đổi củabản cập nhật gây lỗi mà cho kết quả các bản vá tốt hơn so với các công cụ khác.Bảng 3.1 mô tả các loại nguyên liệu sửa lỗi và các mẫu sửa lỗi sử dụng nhữngnguyên liệu này Đối với các biểu thức boolean sẽ dùng làm nguyên liệu cho cáctoán tử sửa lỗi liên quan các cấu trúc câu lệnh điều khiển (if, while, for) Cácnguyên liệu là câu lệnh đơn thì được sử dụng cho mẫu sửa lỗi thêm câu lệnh mới
AddStmt Còn các nguyên liệu là biến, hoặc các biểu thức khác thì được sử dụng
để sửa các lỗi liên quan đến các lời gọi phương thức Những nguyên liệu sửa lỗiđược sử dụng trong phương pháp đề xuất của luận văn này đa dạng hơn Relifix(ví dụ: có thêm nguyên liệu là danh sách các biến và biểu thức)
Trang 363.4 Các mẫu sửa lỗi
Hiện nay, luận văn đã cài đặt tám mẫu sửa lỗi thừa kế từ tư tưởng của Relifix [42]
Những mẫu sửa lỗi này được thiết kế để sửa lỗi cho các chương trình C, tuy
nhiên trong bài báo không chỉ rõ cách cài đặt và không có công cụ kèm theo được
công bố Do vậy, luận văn này nhằm cài đặt lại tư tưởng các mẫu sửa lỗi của
Relifix và áp dụng sửa lỗi và đánh giá phương pháp trên các chương trình Java
Luận văn cũng phân tích và điều tra 51 lỗi hồi quy Java từ 3483 lỗi từ hai bộ bộ dữ
liệu lỗi chuẩn BugSwarm và Bears Từ đó, luận văn đề xuất thêm ba mẫu sửa lỗi
có sử dụng các thông tin thay đổi từ bản cập nhật gây lỗi để sửa lỗi hồi quy cho
các chương trình Java
B ẢNG 3.2: Các mẫu sửa lỗi đã cài đặt
2 Khôi phục câu lệnh thay đổi trở về phiên bản trước
3 Hoán đổi câu lệnh thay đổi và câu lệnh liền kề
5 Chuyển đổi câu lệnh thay đổi thành biểu thức điều
kiện
7 Thêm biểu thức điều kiện vào câu lệnh điều kiện
có sẵn
Bảng 3.2 liệt kê các mẫu sửa lỗi được cài đặt trong công cụ LyFix Những mẫu sửa
lỗi được ghi kí hiệu "3" ở cột Có tham số là những mẫu có sử dụng nguyên liệu sửa lỗi
được thu thập ở những bước trước Các mẫu sửa lỗi từ số thứ tự 1-8 được cài đặt lại và
cải tiến thêm dựa vào tư tưởng của Relifix Ba mẫu sửa lỗi cuối NullChecker,
AddTryCatch, MutateMI là những mẫu sửa lỗi được đề xuất mới trong luận văn này.
Trang 37Phần nội dung tiếp theo của mục này sẽ mô tả về các mẫu sửa lỗi Ngoài ra, Phụlục A mô tả một cách cụ thể các mẫu sửa lỗi này theo một khuôn mẫu chuẩn.
Xóa (các) câu lệnh được thêm nhầm (Delete) Mẫu sửa lỗi này sẽ xóa những
câu lệnh mà nhà phát triển đã thêm nhầm vào ở lịch sử Đầu tiên khi nhận thông
tin về vị trí gây lỗi từ mô-đun FL, mẫu sẽ kiểm tra tại vị trí đó có phải là câu lệnhmới được thêm vào hay không Nếu có, mẫu sẽ tiếp tục tìm các lệnh phía sau mà
có phụ thuộc dòng dữ liệu hoặc luồng dữ liệu mà cũng được thêm vào để xóa tất
cả Ví dụ, Mã nguồn 3.3 mô tả thay đổi ở bản cập nhật sửa lỗi cho lỗi nutz-333553716 Dòng mã nguồn khai báo list, gán giá trị từ kết quả gọi phươngphức pojo.getList(classOfT) bị lỗi vì sai kiểu dữ liệu Vì thế, nếu xóa dòng này sẽsửa được lỗi hiện tại, tuy nhiên bởi vì các dòng mã nguồn tiếp theo sử dụng dữliệu từ list nên cũng cần được loại bỏ để đảm bảo mã nguồn có thể biên dịch Hiệntại mẫu sửa lỗi được cài đặt để xóa các thành phần mã nguồn ở mức câu lệnh
nutzam-M Ã NGUỒN 3.3: Bản cập nhật sửa lỗi cho nutzam-nutz-333553716
- List <T > list = pojo getList ( classOfT );
- if ( list != null && list size () > 0)
- for ( T t : list ) {
- _ f e t c h L i n k s (t , regex , false , true , true , null );
- }
Khôi phục câu lệnh thay đổi trở về phiên bản trước (Revert) Mẫu sửa lỗi này sẽ
cố gắng khôi phục lại phần mã nguồn chương trình ở vị trí gây lỗi về phiên bản trước
bằng cách thay thế những câu lệnh bị sửa đổi hiện tại ở vị trí gây lỗi bằng những câulệnh tương ứng ở phiên bản trước đó Hiện tại mẫu này hỗ trợ khôi phục ở hai mức làmức câu lệnh Các loại hoạt động khôi phục cho mức câu lệnh bao gồm: thêm lại câulệnh đã bị xóa, khôi phục câu lệnh đã được sửa đổi, khôi phục câu lệnh đã được di
chuyển Phần xóa câu lệnh được thêm đã được hỗ trợ bởi mẫu Delete nên không
được cài đặt ở đây Ngoài ra còn có thể áp dụng mẫu này để khôi phục thay đổi ởmức các biểu thức; khai báo thuộc tính, phương thức và lớp Ví dụ ở Mã nguồn 3.4,
bản vá được sinh nhờ việc xóa tham số attributes.length mà trước đó lập trình viên đã
thêm vào Mẫu này được thiết kế để tập trung sửa các lỗi hồi quy Local.
Trang 38M Ã NGUỒN 3.4: Bản cập nhật sửa lỗi cho Bears-251
- a t t r i b u t e s M a p = new ConcurrentHashMap < >( a t t r i b u t e s length );
+ a t t r i b u t e s M a p = new ConcurrentHashMap < >();
Hoán đổi câu lệnh thay đổi và câu lệnh liền kề (Swap) Mẫu sửa lỗi này sẽ hoán
đổi câu lệnh thay đổi ở bản cập nhật gây lỗi với các câu lệnh trước hoặc sau nó Lý
do đề xuất mẫu này là thường lập trình viên sau khi thêm câu lệnh để tạo tính năngmới nhưng lại thêm vào sai vị trí làm cho trạng thái chương trình cũ không còn đúng
và xảy ra lỗi hồi quy Trong những trường hợp này, câu lệnh thay đổi thường có quan
hệ phụ thuộc dữ liệu đối với các câu lệnh liền kề nó Ví dụ ở lỗi Bears-186, Mã nguồn
3.5 và 3.6 lần lượt là các bản cập nhật gây lỗi và bản cập nhật sửa lỗi Trong ví dụ
này, các mẫu Revert và Swap có thể được sử dụng để sửa lỗi Đầu tiên, câu lệnh if được thêm lại vào mã nguồn nhờ mẫu Revert Tuy nhiên, để chương trình chạy đúng,
giá trị của biến interfaceOnly cần được cập nhật bởi câu lệnh gán trước khi thực hiện
câu lệnh if Do vậy, mẫu Swap cần được sử dụng để thực hiện việc này.
M Ã NGUỒN 3.5: Bản cập nhật gây lỗi cho Bears-186
Trang 39Phủ định điều kiện được thêm mới (Negate) Mẫu này sẽ lựa chọn một trong những
biểu thức boolean mới được thêm vào trong bản cập nhật gây lỗi, sau đó thực hiện phủ định giá trị của biểu thức đó Đây là mẫu sửa lỗi được cài đặt dựa vào ý tưởng đề xuất ở
bản vá có thể chấp nhận (plausible patch, là bản vá làm cho toàn bộ ca kiểm thử passed)
mà không phải bản vá đúng (correct patch, vừa làm cho bộ kiểm thử passed, vừa có ý nghĩa tương đồng đối với bản vá đề xuất bởi nhà phát triển).
Chuyển đổi câu lệnh thay đổi thành biểu thức điều kiện (Convert) Mục tiêu sửa
lỗi của mẫu này những câu lệnh thay đổi mà có kiểu trả về là boolean Trong Java,
những loại câu lệnh này chỉ có thể là các lời gọi phương thức Mẫu sẽ thay thế câulệnh này bằng một câu lệnh if với biểu thức điều kiện chính là lời gọi phương thức đó.Đây là mẫu sửa lỗi được đề xuất trong [42], và các lỗi hồi quy Java trong bộ dữ liệuthu thập bởi luận văn này không có trường hợp nào được sửa bởi mẫu này Tuynhiên, mẫu vẫn được cài đặt để có thể đánh giá khách quan phương pháp sửa lỗi hồiquy đề xuất ở [42] đối với các chương trình Java Mã nguồn 3.7 mô tả một ví dụ minhhọa cho ý tưởng của mẫu sửa lỗi này isANumber(a) là một lời gọi phương thức cókiểu trả về là boolean Thay vì chỉ gọi vào lời gọi phương thức này và không làm gì,lập trình nên kiểm tra sự hợp lệ xem a có phải là một số hay không rồi mới thực hiệncâu lệnh tiếp theo int x = (int)a + 1;
M Ã NGUỒN 3.7: Ví dụ minh họa cho mẫu sửa lỗi Revert
- i sA Nu mbe r ( a );
+ if ( isA Nu mb er ( a )) {
int x = ( int ) a + 1;
+ }
Thêm câu lệnh kiểm tra điều kiện (AddIf) Mẫu sửa lỗi là mẫu sửa lỗi tổng quát
hơn so với mẫu Convert Mẫu này sẽ tạo ra các câu lệnh kiểm tra điều kiện
(if-statement) để tránh thực hiện câu lệnh tiếp theo khi nghi ngờ có lỗi Những biểu thứcđiều kiện dùng để kiểm tra sẽ được thu thập từ nguyên liệu sửa lỗi ở bước trước Cácđối tượng mã nguồn có thể áp dụng mẫu sửa lỗi này được chia làm ba loại với cáchsửa khác nhau: câu lệnh khai báo biến, câu lệnh điều kiện và câu lệnh khác
Trang 40Sửa câu lệnh khai báo biến: Trong những câu lệnh này, có thể các đã biến được
khởi tạo giá trị Ví dụ: int a = f(1); thì giá trị được khởi tạo cho biến a ngay tại
thời điểm khai báo là f(1).Ý tưởng sửa lỗi là chỉ khi các chương trình vượt qua
các điều kiện nhất định (được thêm bởi mẫu) thì mới gán các giá trị đó cho biến.Nếu không, một giá trị mặc định sẽ được sử dụng thay thế tùy vào kiểu dữ liệu
của biến Các giá trị mặc định này được mô tả như ở Công thức A.1
Sửa câu lệnh điều kiện: Những câu lệnh điều kiện ở đây là if-statement,
elseif-statement Biểu thức điều kiện của của những câu lệnh này sẽ được
thay thế bằng biểu thức điều kiện mới
Sửa câu lệnh khác: Đối với những loại câu lệnh còn lại này thì một câu lệnh
if-statement được tạo ra chứa biểu thức điều kiện được sử dụng sẽ bọc câu
lệnh cũ tại vị trí gây lỗi Mã nguồn 3.8 mô tả Bản cập nhật sửa lỗi cho
Bears-127 Tại đây, nhà phát triển đã quên kiểm tra giá trị số lượng bytes khả dụng trong đối tượng buf trước khi thực hiện lời gọi buf.readUnsignedShort()
Biểu thức điều kiện được sử dụng để làm điều kiện kiểm tra là buf.readableBytes()
>= 2, là một biểu thức được thêm mới vào ở một ví trị mã nguồn khác trong bản cập nhật gây lỗi
M Ã NGUỒN 3.8: Bản cập nhật sửa lỗi cho Bears-127
- d e c o d e S t a t u s ( position , buf r e a d U n s i g n e d S h o r t ());
+ if ( buf r e a d a b l e B y t e s () >= 2) {
+ d e c o d e S t a t u s ( position , buf r e a d U n s i g n e d S h o r t ());
+ }