Luận văn tập trung giải quyết các bài toán, và đề xuất kĩ thuật sinh dữ liệu kiểm thử đầu tiên dựa trên thông tin phân tích mã nguồn thay vì áp dụng kĩ thuật sinh ngẫu nhiên truyền thống trong kĩ thuật kiểm thử tự động định hướng. Để giảm thiểu số lượng bộ dữ liệu kiểm thử trong khi vẫn đạt độ phủ cao, thuật toán LDFS được đề xuất. Để chứng minh tính hiệu quả của phương pháp đề xuất, công cụ CFT4Cpp được xây dựng dựa trên phương pháp đề xuất và tiến hành so sánh với các phương pháp kiểm thử khác gồm KLEE, PathCrawler, CAUT, CREST.
ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CƠNG NGHỆ Nguyễn Đức Anh PHƯƠNG PHÁP PHÂN TÍCH MÃ NGUỒN VÀ SINH DỮ LIỆU KIỂM THỬ CHO CÁC DỰ ÁN C/C++ Ngành: Công nghệ thông tin Chuyên ngành: Kỹ thuật phần mềm Mã số: 60480103 LUẬN VĂN THẠC SĨ: KỸ THUẬT PHẦN MỀM Cán hướng dẫn: PGS TS Phạm Ngọc Hùng HÀ NỘI - 2017 Kiểm thử đơn vị pha quan trọng để đảm bảo chất lượng cao phần mềm, đặc biệt phần mềm nhúng Hai phương pháp sử dụng phổ biến gồm kiểm thử hộp đen (black-box testing) kiểm thử hộp trắng (white-box testing) Kiểm thử hộp đen kiểm tra tính đắn đầu với đầu vào cho trước mà không quan tâm đến mã nguồn chương trình Ngược lại, phương pháp kiểm thử hộp trắng đánh giá chất lượng mã nguồn cách sử dụng kĩ thuật phân tích mã nguồn Tuy nhiên, kiểm thử hộp trắng sâu vào phân tích mã nguồn nên kĩ thuật cho phép phát lỗi tiềm ẩn mà kiểm thử hộp đen khơng phát Tuy nhiên, chi phí kiểm thử hộp trắng lớn nhiều so với kiểm thử hộp đen Đặc biệt, dự án cơng nghiệp, chi phí kiểm thử hộp trắng chiếm 50% tổng chi phí phát triển phần mềm Nguyên nhân tình trạng số lượng hàm cần kiểm thử lên tới hàng nghìn, chí hàng chục nghìn hàm Kết chi phí để kiểm thử hết hàm lớn, ảnh hưởng nhiều đến tốc độ phát triển dự án Vì thế, trình kiểm thử hộp trắng cần tự động hóa để giải tốn chi phí Hai hướng kiểm thử đơn vị theo phương pháp kiểm thử hộp trắng gồm phát lỗi tối đa hóa độ phủ Cho hàm cần kiểm thử hộp trắng, hàm có lỗi tiềm ẩn khó phát u cầu sinh tập ca kiểm thử để kiểm tra chất lượng hàm Theo hướng đầu tiên, tập ca kiểm thử gây lỗi lỗi chia cho 0, lỗi tràn nhớ Hướng thứ hai yêu cầu sinh tập ca kiểm thử cho số lượng nhánh, câu lệnh, điều kiện thực thi lớn Khái niệm độ phủ liên quan đến chất lượng ca kiểm thử theo hướng tối đa hóa độ phủ Độ phủ lớn đồng nghĩa với chất lượng ca kiểm thử tốt Ví dụ, hàm cần kiểm thử có 10 nhánh mà có nhánh qua tập ca kiểm thử độ phủ đạt 90% Điều có nghĩa hàm có nhánh thừa cần phát hiện, hàm có lỗi tiềm ẩn mà kiểm thử hộp đen khơng phát Các công cụ kiểm thử tiêu biểu theo hướng kể đến PathCrawler, CAUT, CUTE, CREST Đối với toán sinh tập ca kiểm thử để đạt độ phủ tối đa, hai phương pháp kiểm thử hộp trắng sử dụng phổ biến gồm kiểm thử tĩnh (static tesing) kiểm thử động (DSE - dynamic symbolic execution) Tư tưởng phương pháp kiểm thử theo hướng tĩnh sinh ca kiểm thử phân tích mã nguồn Theo phương pháp này, tất cú pháp chương trình cần hỗ trợ phân tích đầy đủ Tốc độ ưu điểm phương pháp kiểm thử theo hướng tĩnh kĩ thuật không yêu cầu thực thi chương trình kĩ thuật DSE 3 Tuy nhiên, phương pháp khó áp dụng cho dự án cơng nghiệp khó để hỗ trợ tất cú pháp ngơn ngữ C/C++ Trái ngược với phương pháp kiểm thử tĩnh, phương pháp kiểm thử DSE khơng u cầu phải phân tích cú pháp chương trình để sinh ca kiểm thử Để giảm chi phí phân tích mã nguồn mà đạt độ phủ tối đa, phương pháp kiểm thử DSE kết hợp q trình phân tích cú pháp chương trình với trình biên dịch KLEE, PathCrawler, DART, CAUT, CREST Bởi thế, phương pháp kiểm thử DSE dễ dàng đạt độ phủ cao với nỗ lực phân tích chương trình nhỏ so với phương pháp kiểm thử theo hướng tĩnh Phương pháp kiểm thử theo hướng động gồm hai kĩ thuật kiểm thử sử dụng phổ biến gồm kĩ thuật EGT (execution generated testing) kĩ thuật concolic Kĩ thuật EGT áp dụng công cụ sinh ca kiểm thử tự động tiếng KLEE (2008) – công cụ đánh giá cao tính hiệu Tư tưởng kĩ thuật EGT vừa biên dịch chạy chương trình vừa sinh ca kiểm thử trực tiếp Chẳng hạn, trình biên dịch gặp điều kiện, ca kiểm thử tương ứng nhánh nhánh sai điều kiện sinh Tại đây, với ca kiểm thử, tiến trình tạo phân tích chương trình theo nhánh đúng/sai Q trình sinh ca kiểm thử dừng ba điều kiện sau thỏa mãn (1) đạt độ phủ tối đa (2) khơng cịn nhánh đúng/sai để phân tích tiếp, (3) đạt đến giới hạn thời gian cho phép Nhược điểm kĩ thuật EGT hiệu suất thấp kiểm thử hàm chứa vịng lặp có số lần lặp lớn, chứa lời gọi đệ quy Khi đó, số tiến trình tạo từ hàng nghìn tới hàng chục nghìn Kĩ thuật thể tính hiệu tìm lỗi tiềm ẩn chương trình EGT xem xét trường hợp xảy Tuy nhiên, kĩ thuật EGT không phù hợp với toán sinh ca kiểm thử đạt độ phủ tối đa khơng cần xem xét hết trường hợp sinh ca kiểm thử Kĩ thuật hay sử dụng gọi concolic đề xuất vào năm 2005 cài đặt lần công cụ DART Sau này, kĩ thuật concolic liên tục cải tiến công cụ PathCrawler, CUTE, CAUT, CREST Trong phương pháp này, ca kiểm thử sinh ngẫu nhiên, sau đẩy vào hàm cần kiểm thử để lấy danh sách câu lệnh qua Với ca kiểm thử, tập ca kiểm thử gọi đường thi hành Ca kiểm thử sinh dựa hai thơng tin gồm (1) tiêu chí độ phủ (phủ câu lệnh/nhánh) (2) trạng thái chương trình Quá trình sinh ca kiểm thử kết thúc (1) độ phủ đạt tối đa, (2) đạt đến giới hạn thời gian Hiện tại, nhiều cơng trình nghiên cứu đưa nhiều chiến thuật chọn đường thi hành khác để sinh ca kiểm thử tăng độ phủ tốt CAUT, CREST, PathCrawler Bởi thế, số lượng ca kiểm thử đạt độ phủ tối ưu nên khiến quy trình quản lý ca kiểm thử dễ dàng Tuy nhiên, kĩ thuật kiểm thử concolic tồn nhiều vấn đề cần giải Vấn đề thứ nhất, ca kiểm thử thường sinh ngẫu nhiên dựa kiểu biến Chẳng hạn, biến có kiểu trỏ cấu trúc xác suất sinh giá trị biến NULL khác NULL 50% DART Kĩ thuật sinh ngẫu nhiên khơng thể tính hiệu chương trình có biến truy cập vùng nhớ, ví dụ hàm chép xâu s1 cho s2 Rõ ràng, giá trị xâu s1 khác NULL Nếu giá trị s1 NULL, chương trình bị lỗi thực thi giá trị Tuy nhiên, kĩ thuật sinh ca kiểm thử theo phương pháp ngẫu nhiên không phát ràng buộc quan trọng Quá trình sinh ca kiểm thử lặp lặp lại đến ca kiểm thử khơng gây lỗi Điều dẫn đến thời gian sinh ca kiểm thử mà không gây lỗi tăng lên Vấn đề thứ hai liên quan đến tốn phân tích chương trình C/C++ Các phương pháp kiểm thử đề xuất CREST, CAUT, PathCrawler, KLEE áp dụng cho ngôn ngữ C mà khơng hỗ trợ C++ Khóa luận hướng đến giải vấn đề kiểm thử concolic tốn kiểm thử dự án C/C++ Mục tiêu khóa luận gồm (1) đề xuất phương pháp sinh ca kiểm thử giải vấn đề ca kiểm thử (2) đề xuất phương pháp phân tích mã nguồn dự án C/C++ để sinh tập ca kiểm thử số lượng nhỏ đạt độ phủ tối đa Tư tưởng phương pháp đề xuất sau Đầu vào tốn gồm tiêu chí độ phủ (câu lệnh/nhánh), số lần lặp tối đa vòng lặp, cận biến số nguyên/kí tự, số phần tử tối đa mảng, hàm cần kiểm thử Đầu tiên, hàm cần kiểm thử phân tích xây dựng đồ thị dịng điều khiển tương ứng Sau đó, tập đường thi hành có đồ thị thu thập cách áp dụng thuật toán duyệt đồ thị theo chiều sâu Tập ca kiểm thử xếp theo thứ tự ưu tiên đó, ví dụ đường ngắn có độ ưu tiên cao Với đường thi hành xếp theo độ ưu tiên, kĩ thuật thực thi tượng trưng SMT-Solver áp dụng để tìm giá trị thỏa mãn đường thi hành Nếu tồn giá trị thỏa mãn, ta coi ca kiểm thử Trạng thái độ phủ đồ thị cập nhật Đồng thời, tập đường thi hành nêu loại bỏ đường thi hành thừa (không tăng độ phủ) Quá trình sinh ca kiểm thử lặp lặp lại đến đạt độ phủ tối đa; đạt đến giới hạn thời gian cho trước Tài liệu tham khảo [1] J Burnim and K Sen 2008 Heuristics for Scalable Dynamic Test Generation In Proceedings of the 2008 23rd IEEE/ACM International Conference on Automated Software Engineering (ASE ’08) IEEE Computer Society, Washington, DC, USA, 443–446 [2] Cristian Cadar, Daniel Dunbar, and Dawson Engler 2008 KLEE: Unassisted and Automatic Generation of High-coverage Tests for Complex Systems Programs In Proceedings of the 8th USENIX Conference on Operating Systems Design and Implementation (OSDI’08) USENIX Association, Berkeley, CA, USA, 209–224 [3] Cristian Cadar and Koushik Sen 2013 Symbolic Execution for Software Testing: Three Decades Later Commun ACM 56, (Feb 2013), 82–90 [4] Leonardo De Moura and Nikolaj Bjørner 2008 Z3: An Efficient SMT Solver In Proceedings of the Theory and Practice of Software, 14th International Conference on Tools and Algorithms for the Construction and Analysis of Systems (TACAS’08/ETAPS’08) SpringerVerlag, Berlin, Heidelberg, 337–340 [5] Patrice Godefroid, Nils Klarlund, and Koushik Sen 2005 DART: Directed Automated Random Testing In Proceedings of the 2005 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI ’05) ACM, New York, NY, USA, 213–223 8 [6] James C King 1976 Symbolic Execution and Program Testing Commun ACM 19, (July 1976), 385–394 [7] Guodong Li, Indradeep Ghosh, and Sreeranga P Rajan 2011 KLOVER: A Symbolic Execution and Automatic Test Generation Tool for C++ Programs In Proceedings of the 23rd International Conference on Computer Aided Verification (CAV’11) SpringerVerlag, Berlin, Heidelberg, 609–615 [8] George C Necula, Scott McPeak, Shree Prakash Rahul, and Westley Weimer 2002 CIL: Intermediate Language and Tools for Analysis and Transformation of C Programs In Proceedings of the 11th International Conference on Compiler Construction (CC ’02) Springer-Verlag, London, UK, UK, 213–228 [9] D A Nguyen, P N Hung, and V H Nguyen 2016 A method for automated unit testing of C programs In 2016 3rd National Foundation for Science and Technology Development Conference on Information and Computer Science (NICS) 17–22 [10] Dirk Riehle 1997 Composite Design Patterns In Proceedings of the 12th ACM SIGPLAN Conference on Object-oriented Programming, Systems, Languages, and Applications (OOPSLA ’97) ACM, New York, NY, USA, 218–228 [11] Koushik Sen, Darko Marinov, and Gul Agha 2005 CUTE: A Concolic Unit Testing Engine for C In Proceedings of the 10th European Software Engineering Conference Held Jointly with 13th ACM SIGSOFT International Symposium on Foundations of Software Engineering (ESEC/FSE-13) ACM, New York, NY, USA, 263–272 [12] T Su, G Pu, B Fang, J He, J Yan, S Jiang, and J Zhao 2014 Automated CoverageDriven Test Data Generation Using Dynamic Symbolic Execution In 2014 Eighth International Conference on Software Security and Reliability (SERE) 98–107 [13] Z Wang, X Yu, T Sun, G Pu, Z Ding, and J Hu 2009 Test Data Generation for Derived Types in C Program In 2009 Third IEEE International Symposium on Theoretical Aspects of Software Engineering 155– 162 [14] Nicky Williams, Bruno Marre, Patricia Mouy, and Muriel Roger 2005 PathCrawler: Automatic Generation of Path Tests by Combining Static and Dynamic Analysis In Proceedings of the 5th European Conference 10 on Dependable Computing (EDCC’05) Springer-Verlag, Berlin, Heidelberg, 281–292 ... toán kiểm thử dự án C/C++ Mục tiêu khóa luận gồm (1) đề xuất phương pháp sinh ca kiểm thử giải vấn đề ca kiểm thử (2) đề xuất phương pháp phân tích mã nguồn dự án C/C++ để sinh tập ca kiểm thử. .. cú pháp ngơn ngữ C/C++ Trái ngược với phương pháp kiểm thử tĩnh, phương pháp kiểm thử DSE khơng u cầu phải phân tích cú pháp chương trình để sinh ca kiểm thử Để giảm chi phí phân tích mã nguồn. .. dụng kĩ thuật phân tích mã nguồn Tuy nhiên, kiểm thử hộp trắng sâu vào phân tích mã nguồn nên kĩ thuật cho phép phát lỗi tiềm ẩn mà kiểm thử hộp đen không phát Tuy nhiên, chi phí kiểm thử hộp