Cách sử dụng các công cụ mpv, otg, ct

Một phần của tài liệu Nghiên cứu ứng dụng “NModel” trong việc phát triển hệ thống nhúng thời gian thực (Trang 53)

4.1.2.1. Công cụ mpv

Công cụ mpv đƣợc sử dụng để hình dung và phân tích hành vi của một hoặc nhiều chƣơng trình. Nó thực hiện thăm dò, nó tạo ra một máy trạng thái hữu hạn FSM từ một MP. MPV hiển thị đồ thị của FSM đƣợc tạo, đồng thời khảo sát và hiển thị thành phần của tất cả các chƣơng trình mô hình đƣợc có tên trên dòng lệnh, nó có thể là các MP C# hoặc các FSM. MPV cung cấp nhiều lựa chọn (trên dòng lệnh và giao diện sử dụng của nó) để điều chỉnh đồ thị đƣợc hiển thị, lƣu trữ và khôi phục các kết quả của việc thăm dò. Nó cũng cung cấp cơ sở để kiểm tra các trạng thái (biến chƣơng trình và giá trị của chúng), và để khám phá các chƣơng trình tƣơng tác (từng bƣớc, làm việc chuyển tiếp từ một vài trạng thái quan tâm).

Bằng cách tìm kiếm FSM, mpv có thể thực hiện phân tích an toàn để kiểm tra xem hệ thống có đạt đƣợc các trạng thái bị cấm không, và phân tích tính hoạt động đƣợc để xác định các trạng thái chết.

Công cụ mpv đòi hỏi phần mềm GLEE phải đƣợc cài đặt. Các công cụ còn lại không yêu cầu GLEE.

Cách sử dụng (Usage) mpv: mpv [/reference:<string>]*[/mp:<string>]* /initialTransitions:<int>]* [/transitionLabels:{None|ActionSymbol|Action}]* [/nodeLabelsVisible[+|-]]* [/initialStateColor:<string>]* [/hoverColor:<string>]* [/selectionColor:<string>]* [/deadStateColor:<string>]* [/deadStatesVisible[+|-]]* [/unsafeStateColor:<string>]* [/maxTransitions:<int>]* [/loopsVisible[+|-]]* [/mergeLabels[+|-]]* [/acceptingStatesMarked[+|-]]* [/stateShape:{Box|Circle|Diamond|Ellipse|Octagon|Plaintext}]* [/direction:{TopToBottom|LeftToRight|RightToLeft|BottomToTop}]* [/combineActions[+|-]]* [/livenessCheckIsOn[+|-]]* [/safetyCheckIsOn[+|-]]*

[/testSuite:<string>]* [/fsm:<string>]* [/startTestAction:<string>]* [/group:<string>]* <model>* @<file> Ví dụ: mpv @mpv args.txt mpv /fsm:M1.txt /fsm:M2.txt mpv /testSuite:ContractTest.txt mpv /r:NewsReaderUI.dll NewsReader.Factory.Create mpv /r:NewsReaderUI.dll /mp:NewsReader

mpv /r:Controller.dll Reactive.Factory.Create /safetyCheckIsOn+ mpv /r:Controller.dll /mp:Reactive /safetyCheckIsOn+

41.2.2. Công cụ otg

Công cụ otg tạo ra một bộ kiểm thử ngoại tuyến (offline test suite) mà đạt đƣợc độ bao phủ liên kết của máy trạng thái hữu hạn (FSM) đƣợc tạo ra từ một MP. Sau đó, bộ kiểm thử có thể đƣợc thực hiện bởi Conformance Tester (công cụ ct).

Cách sử dụng otg:

otg [/reference:<string>]* [/mp:<string>]* [/file:<string>]* [/append[+|-]]* [/fsm:<string>]* <model>* @<file>

Ví dụ:

otg @otg args.txt

otg /r:ClientServer.dll ClientServer.Factory.Create /fsm:Scenario.txt otg /r:ClientServer.dll /mp:ClientServer /fsm:Scenario.txt

otg /r:ClientServer.dll ClientServer.Factory.Create /file:ContractTest.txt

otg /r:ClientServer.dll /mp:ClientServer /file:ContractTest.txt

4.1.2.3. Công cụ ct

Để thực hiện các test bằng cách sử dụng test runner ct, một bản khai thác kiểm thử phải đƣợc viết bằng C# để kết nối thực hiện đến ct. Một bộ kiểm thử đƣợc tạo ra từ một MP bởi công cụ otg, hoặc ct có thể tạo ra các ca kiểm thử trực tiếp từ một MP khi test run thực thi, và một chiến lƣợc tùy chỉnh có thể đƣợc viết bằng C# mà ct sử dụng để tối đa hóa độ bao phủ theo tiêu chí đƣợc xác định.

ct /iut:<string> [/modelStepper:<string>] /reference:<string>+ [/mp:<string>]*

[/coverage:<string>]* [/steps:<int>]* [/maxSteps:<int>]* [/runs:<int>]*

[/observableAction:<string>]* [/cleanupAction:<string>]* [/internalAction:<string>]* [/waitAction:<string>]* [/timeoutAction:<string>]*

[/timeout:<int>]* [/continueOnFailure[+|-]]* [/logfile:<string>]* [/randomSeed:<int>]* [/overwriteLog[+|-]]* [/testSuite:<string>]* [/fsm:<string>]* [/startTestAction:<string>]* <model>* @<file>

Ví dụ:

ct @ct args.txt

ct /r:Stepper.dll /iut:ClientServerImpl.Stepper.Create /testSuite:ContractTest.txt

ct /r:ClientServer.dll ClientServer.Factory.Create /r:Stepper.dll ^ /iut:ClientServerImpl.Stepper.Create /fsm:Scenario.txt /runs:1 ct /r:ClientServer.dll /mp:ClientServer /r:Stepper.dll ^

/iut:ClientServerImpl.Stepper.Create /fsm:Scenario.txt /runs:1

4.2. Xây dựng và thực nghiệm với demo hệ thống client/server 4.2.1. Mô tả bài toán 4.2.1. Mô tả bài toán

Trong luận văn này, tôi chọn bài toán về hệ thống nhúng để kiểm thử với NModel là thiết bị điều khiển từ xa – hệ thống client/server. Bài toàn này đƣợc tham khảo trong tài liệu [4]. Đây là một ứng dụng nhỏ nhƣng tƣơng đối đầy đủ. Mục đích của bài toán là phát triển một hệ thống thiết bị phòng thí nghiệm bao gồm một cảm biến nhiệt độ kết nối với một máy tính nhúng, một mạng, và một máy tính khác đƣợc sử dụng để lƣu trữ và phân tích dữ liệu (hình 4.1). Trên máy tính nhúng (Server) có một chƣơng trình giám sát nhiệt độ đƣợc cài đặt. Trên máy tính khác (Client) có một chƣơng trình khai thác dữ liệu đƣợc cài đặt. Các chƣơng trình giao tiếp với nhau qua mạng bằng cách sử dụng giao thức TCP/IP (hình 4.2), vì vậy client có thể sử dụng internet để kết nối tới một server trong một nhà máy ở xa hoặc trạm thời tiết.

Hình 4.1. Thiết bị điều khiển từ xa – Hệ thống Client/Server

Trƣớc khi kiểm thử và phân tích ứng dụng demo đƣợc mô tả, tôi sẽ giải thích một số vấn đề về cách mà chƣơng trình làm việc.

Protocol

Hai chƣơng trình thực hiện cùng một giao thức, một thỏa thuận về cách làm việc cùng nhau. Một giao thức đƣợc xác định bởi các quy tắc để hình thành những thông điệp và các quy tắc mà ràng buộc theo thứ tự các thông điệp. Trong demo này, "các thông điệp" trong giao thức là các lời gọi phƣơng thức đã đƣợc mã hóa (coded).

Trong giao thức này, máy chủ bắt đầu trƣớc, và đợi một kết nối từ một máy khách. Máy khách kết nối tới máy chủ và gửi một lệnh yêu cầu một phép đo nhiệt độ. Máy chủ phản hồi bằng cách gửi trả lại nhiệt độ. Sau đó máy khách có thể gửi một dòng lệnh khác, hoặc có thể đóng kết nối và thoát. Nếu client đóng, server có thể đợi một client khác để kết nối, hoặc có thể thoát. Server có thể chỉ chứa một kết nối client tại một thời điểm.

Hình 4.2: Giao thức client/server Sockets

Giao thức của demo đƣợc thực hiện bằng cách sử dụng các socket, một giao diện lập trình ứng dụng API cho giao tiếp qua mạng TCP/IP. Socket API là một trong những kỹ thuật cơ bản của Internet và quen thuộc với nhiều nhà phát triển. Khung làm việc .Net cung cấp một thực hiện của API này trong lớp Socket trong không gian tên

System.Net.Sockets.

Thiết lập một kết nối yêu cầu nhiều bƣớc, trong đó mỗi một đối tác gọi các phƣơng thức trong socket API. Trong Server, Socket tạo một socket nghe (a listener socket), Bind liên kết nó với một địa chỉ IP và số cổng, và Listen chuẩn bị cho một kết nối. Accept thực hiện kết nối và tạo một connection socket để sử dụng cho kết nối. Trong Client, Socket tạo một cổng và Connect thực hiện kết nối. Khi kết nối đƣợc thực hiện, cả hai đối tác gọi SendReceive để trao đổi thông điệp. Trong giao thức của

demo, client gửi đầu tiên. Cả hai đối tác gọi Close để kết thúc kết nối. Client đóng trƣớc. Cuối cùng, server gọi Close trên socket nghe của nó.

Libraries

Giống nhƣ hầu hết các ứng dụng, chƣơng trình “Monitor”“Logger” của demo sử dụng các thƣ viện. Chúng không gọi trực tiếp API các socket .Net. Thay vì đó, chúng gọi các phƣơng thức trong lớp Client Server đƣợc xây dựng. Những lớp này là các hàm bao (wrappers) cho các socket, .Net cung cấp một API tƣơng tự nhƣng đơn giản mà nó là chuyên ngành cho các ứng dụng thiết bị điều khiển từ xa. Mỗi một phƣơng thức hàm bao Socket, Bind gọi phƣơng thức socket .Net với tên giống nhau, nhƣng sử dụng ít tham số hơn, hoặc các tham số thuận tiện hơn. Ví dụ, các phƣơng thức Receive của client và Send của Server xử lý các số dấu chấm phẩy động (các mẫu nhiệt độ) mà không phải là mảng của byte.

4.2.2. Kiểm thử demo bằng NModel 4.2.2.1. Kiểm thử ngoại tuyến (Offline) 4.2.2.1. Kiểm thử ngoại tuyến (Offline)

Quy trình kiểm thử chƣơng trình bằng NModel thông qua các bƣớc sau: xây dựng implementation, viết MP, sử dụng mpv để hình dung và phân tích, sử dụng otg để sinh bộ kiểm thử tự động, cuối cùng là sử dụng công cụ ct để chạy một bộ kiểm thử. Bƣớc đầu tiên là xây dựng hai MP đầu vào từ thực hiện (implementation) client/server đã đƣợc xây dựng, đó là MP hợp đồng ClientServer (M1) và MP kịch bản (M2):

MP ClientServer M1:

Mục đích của M1: là biểu diễn hệ thống phân tán với các chƣơng trình chạy trên hai máy tính đƣợc kết nối mạng. Client và Server thực hiện trong một chủ để duy nhất, đan xen các cuộc gọi phƣơng thức của chúng theo một trật tự phù hợp với giao thức của chúng (hình 4.2). Tự động sinh và kiểm chứng các test run.

Các hành động: Các hành động của client và server là riêng biệt. Việc gửi và nhận của client không giống với việc gửi và nhận của server. Do đó, các hành động bao gồm: ClientSend, ServerSend, ClientReceive, và ServerReceive.

Các biến trạng thái: Trong ví dụ này, có hai loại ràng buộc theo trình tự đó là: Socket phải đƣợc tạo (Created), đƣợc kết nối (Connected), và đóng theo giao thức. Các hành động gửi và nhận phải thay thế, luôn luôn bắt đầu với hành động gửi. Do đó, có 3 biến trạng thái cho trạng thái điều khiển là: ClientSocket, ServerSocket và Phase.

Trạng thái dữ liệu: là nhiệt độ đƣợc lƣu trữ trong bộ đệm nhận dữ liệu của client

clientBuffer.

Giá trị mong đợi trả về đƣợc tính toán sẵn: giới hạn 2 nhiệt độ là 99.9 và 100.0. Viết mã: các mã đƣợc viết bằng C# theo cấu trúc MP (chi tiết trong phần phụ lục).

MP kịch bản M2: đƣợc biểu diễn bởi máy trạng thái hữu hạn, M2 đƣợc lƣu trữ trong file scenario.txt:

Transitions( t(0,ServerSocket(),1), t(1,ServerBind(),2), t(2,ServerListen(),3), t(3,ClientSocket(),4), t(4,ClientConnect(),5), t(5,ServerAccept(),6), t(6,ClientClose(),7), t(7,ServerCloseConnection(),8), t(8,ServerClose(),9)))

Bƣớc thứ hai, sau khi đã có các MP đầu vào thì tiến hành phân tích chúng bằng công cụ mpv theo trình tự sau:

 Khởi động chƣơng trình cmd.exe.

 Gõ lệnh >build.bat để xây dựng các chƣơng trình thƣ viện.

 Gõ lệnh >mpv @mpv_contract.txt để hiển thị FSM đúng của MP. Khi đó đƣợc kết quả nhƣ hình 4.3:

Hình 4.3: FSM đúng của MP hợp đồng

Hình 4.3 hiển thị toàn bộ các trạng thái và đƣờng chạy (runs) của MP, trạng thái đƣợc đánh dấu đƣờng viền đậm là trạng thái kết thúc (trạng thái chấp nhận). Các trạng thái đƣợc tô màu vàng là các trạng thái không an toàn hoặc trạng thái chết.

 Gõ lệnh >mpv @mpv_scenario.txt để hiển thị FSM của MP kịch bản. Kết quả là FSM chỉ có duy nhất một đƣờng chạy đƣợc hiển thị nhƣ trong hình 4.4.

Hình 4.4: FSM của MP kịch bản

 Gõ lệnh >mpv @mpv_composition.txt để hiển thị FSM của MP kịch bản đƣợc biên soạn cùng với MP hợp đồng (FSM có sử dụng điều khiển kịch bản). Kết quả , ta nhận đƣợc thể hiện trong hình 4.5. FSM này đã đƣợc giới hạn tối ƣu về số lƣợng đƣờng chạy so với FSM của MP hợp đồng.

Bƣớc thứ ba, tạo các bộ kiểm thử (test suite) bởi công cụ otg:

 Gõ lệnh >otg @otg_contract.txt để tạo một bộ kiểm thử cho trƣờng hợp sử dụng MP hợp đồng. Tên tệp tin test suite là ContractTest.txt đƣợc lƣu trữ tự động trong cùng thƣ mục của MP. Bộ ca kiểm thử này gồm có 6 ca kiểm thử có nội dung nhƣ sau:

TestSuite( TestCase( ServerSocket(), ServerBind(), ClientSocket(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("99,9")), ServerCloseConnection(), ServerClose(), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ClientClose() ), TestCase( ClientSocket(), ServerSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ClientSend(), ServerReceive(), ServerSend(double("99,9")), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ServerCloseConnection(), ServerClose(), ClientClose() ), TestCase( ClientSocket(), ServerSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("100")), ServerCloseConnection(), ClientReceive_Start(), ClientReceive_Finish(double("100")), ClientClose(), ServerClose() ), TestCase(

ServerSocket(), ServerBind(), ServerListen(), ClientSocket(), ClientConnect(), ServerAccept(), ClientClose(), ServerCloseConnection(), ServerClose() ), TestCase( ServerSocket(), ClientSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("100")), ClientReceive_Start(), ClientReceive_Finish(double("100")), ServerSend(double("100")), ServerCloseConnection(), ServerClose(), ClientReceive_Start(), ClientReceive_Finish(double("100")), ClientClose() ), TestCase( ClientSocket(), ServerSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("99,9")), ServerCloseConnection(), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ClientClose(), ServerClose() ) )

 Sau khi tạo bộ ca kiểm thử thì dùng lệnh >mpv @mpv_contract_test.txt để xem kết quả của bộ ca kiểm thử dƣới dạng FSM nhƣ trong hình 4.6.

 Gõ lệnh >otg @otg_scenario.txt để tạo ra một bộ ca kiểm thử đƣợc sinh ra từ MP hợp đồng đƣợc biên soạn với MP kịch bản (tên bộ kiểm thử là ScenarioTest.txt). Bộ kiểm thử này gồm có một ca kiểm thử duy nhất có nội dung nhƣ sau:

TestSuite( TestCase(

ServerBind(), ServerListen(), ClientSocket(), ClientConnect(), ServerAccept(), ServerSend(double("100")), ClientReceive_Start(), ClientReceive_Finish(double("100")), ServerSend(double("99,9")), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ClientSend(), ServerReceive(), ClientClose(), ServerCloseConnection(), ServerClose() ) )

 Sau đó sử dụng lệnh >mpv @mpv_scenario_test.txt để xem kết quả của bộ kiểm thử dƣới dạng FSM nhƣ trong hình 4.7.

Hình 4.7: FSM của một bộ kiểm thử đƣợc tạo khi MP hợp đồng biên soạn với MP kịch bản

Bƣớc cuối cùng là dùng công cụ ct để kiểm thử:

 Để chạy đƣợc kiểm thử, đầu tiên phải viết một bản khai thác kiểm thử (stepper) để kết nối implementation tới ct (stepper đƣợc trình bày trong phần phụ lục).  Gõ lệnh >build để xây dựng các thƣ viện của chƣơng trình

 Gõ lệnh >ct @ct_contract.txt để thực hiện kiểm thử ngoại tuyến từ MP hợp đồng (không sử dụng điều khiển kịch bản). Kết quả kiểm thử đƣợc thể hiện trong hình 4.8. Kiểm thử này báo thành công và không phát hiện ra lỗi hay khuyết tật.

 Gõ lệnh >ct @ct_scenario.txt để thực hiện kiểm thử ngoại tuyến đƣợc tạo ra từ MP hợp đồng đƣợc biên soạn với MP kịch bản. Kết quả của kiểm thử này báo lỗi đƣợc thể hiện nhƣ trong hình 4.9.

Hình 4.8: Kết quả kiểm thử ngoại tuyến với trƣờng hợp sử dụng MP hợp đồng

Hình 4.9: Kết quả kiểm thử ngoại tuyến với trƣờng hợp sử dụng điều khiển kịch bản (MP hợp đồng đƣợc biên soạn với MP kịch bản)

Nhƣ vậy là kiểm thử ngoại tuyến chƣơng trình client/server đã phát hiện ra lỗi (hình 4.9) khi một bộ kiểm thử có sử dụng điều khiển kịch bản. Thông điệp chỉ ra rằng kiểm thử này lỗi bởi vì giá trị trả về thực tế trong hành động cuối cùng là 99, không giống nhƣ giá trị trả về mong đợi 99.9 đã đƣợc tính bởi MP và đƣợc lƣu trữ trong ca kiểm thử.

Phân tích lỗi: Sau một vài điều tra tôi phát hiện ra khuyết tật là do các đoạn mã không chính xác (không đúng) gây ra các thất bại. Trong mã lệnh (code) của lớp Client đƣợc xây dựng có bộ đệm nhận của client chỉ đƣợc gán với 4 bytes long. Trong khi đó, tôi lại dự định là 40 chứ không phải 4. Đây là một lỗi đánh máy mà không bị bắt (caught) bởi trình biên dịch, bởi sự kiểm tra hoặc kiểm thử đơn vị. Khi server gửi nhiều hơn 4 ký tự, ví dụ nhƣ 100.0 thì client chỉ đọc đƣợc 4 ký tự đầu tiên là 100. Và sau đó các ký tự còn lại trong bộ đệm sẽ đƣợc nhận vào lần tiếp theo khi Client gọi phƣơng thức Receive. Bằng cách này, một mẫu nhiệt độ đơn giản có thể gây cho Client trở nên không đồng bộ với Server, kết quả là việc đọc không đúng sẽ xảy ra với một hoặc nhiều mẫu nhiệt độ tiếp theo.

Từ các kết quả kiểm thử trên tôi có thể so sánh kết quả và đánh giá kiểm thử ngoại tuyến trong hai trƣờng hợp kiểm thử ngoại tuyến không dùng điều khiển kịch bản (tức là chỉ sử dụng MP hợp đồng để sinh các test case tự động) và kiểm thử ngoại tuyến có sử dụng điều khiển kịch bản (kết hợp MP hợp đồng và MP kịch bản) nhƣ sau: trƣờng hợp không dùng điều khiển kịch bản thì có bộ test suite với nhiều test case nên việc kiểm thử không đƣợc kỹ lƣỡng và triệt để, do đó sẽ ít phát hiện ra lỗi hơn, cụ thể trong bài toán này là kiểm thử thành công không phát hiện đƣợc lỗi hay khuyết tật. Còn với trƣờng hợp có sử dụng điều khiển kịch bản thì bộ test suite có số lƣợng test case tối ƣu hơn (ở đây cụ thể là 1 test case) do đó việc kiểm thử sẽ đƣợc kỹ lƣỡng và triệt để hơn, sẽ phát hiện ra lỗi và khuyết tật tốt hơn.

4.2.2.2. Kiểm thử on-the-fly

Kiểm thử on-the-fly không cần phải tạo một bộ kiểm thử trƣớc mà chỉ cần implementation hoặc MP hoặc stepper. Kiểm thử on-the-fly là kiểm thử ngẫu nhiên.

Bƣớc 1: Tạo file ct_contract_random.txt với nội dung sau: /r:Stepper.dll

/iut:ClientServerImpl.Stepper.Create /r:...\Model\ClientServer.dll

/mp:ClientServer /runs:1

Bƣớc 2: Trên dòng lệnh cmd gõ lệnh >ct @ct_contract_random.txt để thực hiện kiểm thử ngẫu nhiên trong trƣờng hợp sử dụng MP hợp đồng. Kết quả kiểm thử này thông báo là gặp thất bại nhƣ trong hình 4.10.

Hình 4.10: Kết quả kiểm thử ngẫu nhiên khi sử dụng MP hợp đồng

Kiểm thử này bị gián đoạn dẫn đến trạng thái chết (mặc dù chọn ngẫu nhiên bất kỳ đƣờng chạy nào). Để kiểm thử đạt kết quả tốt, tệp tin ct đƣợc tạo có sử dụng điều khiển kịch bản ct_scenario_random.txt với nội dung sau:

/r:Stepper.dll /iut:ClientServerImpl.Stepper.Create /r:..\Model\ClientServer.dll /mp:ClientServer /fsm:..\Model\Scenario.txt /runs:1

Tiếp theo, trên chƣơng trình cmd gõ lệnh >ct @ct_scenario_random.txt để thực hiện kiểm thử ngẫu nhiên với trƣờng hợp sử dụng điều khiển kịch bản. Kết quả kiểm thử đƣợc chỉ ra nhƣ trong hình 4.11.

Một phần của tài liệu Nghiên cứu ứng dụng “NModel” trong việc phát triển hệ thống nhúng thời gian thực (Trang 53)