/[eiffelstudio]/branches/eth/eve/Src/library/testing/etf/interpreter/itp_interpreter.e
ViewVC logotype

Contents of /branches/eth/eve/Src/library/testing/etf/interpreter/itp_interpreter.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88874 - (show annotations)
Thu Jun 14 14:25:07 2012 UTC (7 years, 4 months ago) by jasonw
File size: 59410 byte(s)
1. Fixed a bug in AutoTest which caused some faults to be dropped by test case serialization.
2. Fixed a bug in AutoTest which generates wrong fault ids for online statistics file.
1 ´╗┐note
2 description: "[
3 Interpreter for line based Eiffel like interpreter language.
4 Depends on a generated Erl-G reflection library.
5 ]"
6 author: "Andreas Leitner"
7 date: "$Date$"
8 revision: "$Revision$"
9
10 class ITP_INTERPRETER
11
12 inherit
13 ANY
14
15 EXCEPTIONS
16
17 ARGUMENTS
18 export {NONE} all end
19
20 ITP_SHARED_CONSTANTS
21 export {NONE} all end
22
23 ERL_CONSTANTS
24 export {NONE} all end
25
26 EXECUTION_ENVIRONMENT
27 rename
28 command_line as command_line_arguments
29 export
30 {NONE} all
31 end
32
33 EQA_EXTERNALS
34
35 EQA_TEST_CASE_SERIALIZATION_UTILITY
36
37 create
38 execute
39
40 feature {NONE} -- Initialization
41
42 execute
43 -- Execute interpreter.
44 -- Command line for current: interpreter <port> <melt feature id> <log file>
45 -- <port> is the port number used in socket IPC
46 -- <melt feature id> is the feature body ID whose byte-code is to be injected
47 -- <log file> is the file to store logs.
48 local
49 l_log_filename: STRING
50 l_server_url: STRING
51 l_port: INTEGER
52 l_tc_serialization_file_name: STRING
53 l_state_file_name: FILE_NAME
54 do
55 if argument_count < 6 then
56 check Wrong_number_of_arguments: False end
57 end
58 -- Read command line argument
59 l_server_url := argument (1)
60 l_port := argument (2).to_integer
61 byte_code_feature_body_id := argument (3).to_integer
62 byte_code_feature_pattern_id := argument (4).to_integer
63 l_log_filename := argument (5)
64 interpreter_log_directory := l_log_filename.substring (1, l_log_filename.count - 19)
65 should_generate_log := argument (6).to_boolean
66
67 -- Setup file to store serialized test case.
68 if argument_count = 12 then
69 is_passing_test_case_serialized := argument (7).to_boolean
70 is_failing_test_case_serialized := argument (8).to_boolean
71 l_tc_serialization_file_name := argument (9)
72 is_test_case_serialization_enabled := True
73 is_duplicated_test_case_serialized := argument (10).to_boolean
74 is_post_state_serialized := argument (11).to_boolean
75 is_last_test_case_serialization_passed_to_proxy := argument (12).to_boolean
76 else
77 is_failing_test_case_serialized := True
78 l_tc_serialization_file_name := ""
79 is_test_case_serialization_enabled := False
80 end
81
82 -- Redirect standard output to `output_buffer'.
83 create output_buffer.make (buffer_size)
84 create error_buffer.make (buffer_size)
85
86 -- Create object pool
87 create store.make
88 store.set_is_typed_search_enabled (is_test_case_serialization_enabled)
89
90 -- Create agent creation information book-keeper.
91 create agent_creation_info.make (200)
92
93 -- Create storage for object state retrieval.
94 initialize_query_value_holders
95
96 create primitive_types.make (10)
97 primitive_types.put (1, "INTEGER_32")
98 primitive_types.put (2, "BOOLEAN")
99
100 -- Create log file.
101 create log_file.make_open_append (l_log_filename)
102 if not log_file.is_open_write then
103 report_error ("could not open log file '" + l_log_filename + "'.")
104 die (1)
105 end
106
107 -- Create file for serialized test cases.
108 if not l_tc_serialization_file_name.is_empty then
109 create test_case_serialization_file.make_open_append (l_tc_serialization_file_name)
110 if not test_case_serialization_file.is_open_write then
111 report_error ("could not open test case serialization file '" + l_tc_serialization_file_name + "'.")
112 die (1)
113 end
114 end
115
116 -- Create file to store test case states.
117 create l_state_file_name.make_from_string (interpreter_log_directory)
118 l_state_file_name.set_file_name ("states.txt")
119 create test_state_file.make_open_append (l_state_file_name.out)
120 if not test_state_file.is_open_write then
121 report_error ("could not open test state file '" + l_state_file_name.out + "'.")
122 die (1)
123 end
124
125 -- Initialize precondition table.
126
127 -- Initialize predicate related data structure.
128 initialize_predicates
129
130 create internal
131
132 -- Create test case serializer.
133 create test_case_serializer.make (Current, is_post_state_serialized)
134
135 start (l_port, (create {INET_ADDRESS_FACTORY}).create_loopback)
136
137 -- Close log file.
138 log_file.close
139
140 -- Close test case serialization file.
141 if test_case_serialization_file /= Void and then not test_case_serialization_file.is_closed then
142 test_case_serialization_file.close
143 end
144
145 -- Close test states file.
146 if test_state_file /= Void and then not test_state_file.is_closed then
147 test_state_file.close
148 end
149 end
150
151 start (a_port: INTEGER; a_server_url: INET_ADDRESS)
152 -- Connect to EiffelStudio and initiate `main_loop'.
153 require
154 a_server_url_attached: a_server_url /= Void
155 a_port_valid: a_port >= 0
156 local
157 l_excpt_trace: like exception_trace
158 l_trace: STRING
159 do
160 create socket.make_client_by_address_and_port (a_server_url, a_port)
161 socket.connect
162 socket.set_blocking
163 socket.set_nodelay
164 -- Wait for test cases and then execute test cases in a loop.
165 log_message ("<session>%N")
166 main_loop
167 log_message ("</session>%N")
168 rescue
169 -- Get an one line trace by replacing new line characters with space, since
170 -- the stream parser from proxy cannot deal with multi line error messages.
171 -- TODO: Added support for multi line error message.
172 l_excpt_trace:= exception_trace
173 check l_excpt_trace /= Void end
174 l_trace := l_excpt_trace.twin
175 l_trace.replace_substring_all ("%N", " ")
176
177 report_error ("internal. " + l_trace)
178 log_internal_error (l_excpt_trace)
179 log_message ("</session>%N")
180 die (1)
181 end
182
183 feature -- Status report
184
185 has_error: BOOLEAN
186 -- Has an error occured while parsing?
187
188 is_last_protected_execution_successful: BOOLEAN
189 -- Was the last protected execution successful?
190 -- (i.e. did it not trigger an exception)
191
192 should_quit: BOOLEAN
193 -- Should main loop quit?
194
195 is_request_type_valid (a_type: NATURAL_32): BOOLEAN
196 -- Is `a_type' a valid request type?
197 do
198 Result :=
199 a_type = start_request_flag or else
200 a_type = quit_request_flag or else
201 a_type = execute_request_flag or else
202 a_type = object_state_request_flag or else
203 a_type = type_request_flag or else
204 a_type = precondition_evaluation_request_flag or else
205 a_type = predicate_evaluation_request_flag or else
206 a_type = execute_agent_creation_flag or else
207 a_type = execute_batch_assignment_flag
208 end
209
210 is_last_request_batch_assignment: BOOLEAN
211 -- Is last request batch assignment?
212 do
213 Result := last_request_type = execute_batch_assignment_flag
214 end
215
216 should_generate_log: BOOLEAN
217 -- Should interpreter log be generated?
218
219 is_failing_test_case_serialized: BOOLEAN
220 -- Should only failed test cases be serialized?
221 -- Only has effect when serialization is enabled.
222
223 is_passing_test_case_serialized: BOOLEAN
224 -- Should passing test case be serialized?
225 -- Only has effect when serialization is enabled.
226
227 is_post_state_serialized: BOOLEAN
228 -- Should post-state information be serialized?
229
230 feature -- Access
231
232 variable_at_index (a_index: INTEGER): detachable ANY
233 -- Object in `store' at position `a_index'.
234 local
235 b: BOOLEAN
236 do
237 Result := store.variable_value (a_index)
238
239 -- Uncomment for debugging
240 -- b := {ISE_RUNTIME}.check_assert (False)
241 -- if Result /= Void then
242 -- log_message ("Load object: " + {ITP_SHARED_CONSTANTS}.variable_name_prefix + a_index.out + ": " + Result.generating_type.name + "%N")
243 -- else
244 -- log_message ("Load object: " + {ITP_SHARED_CONSTANTS}.variable_name_prefix + a_index.out + ": Void%N")
245 -- end
246 -- b := {ISE_RUNTIME}.check_assert (b)
247 end
248
249 interpreter_log_directory: STRING
250 -- Directory to store file interpreter_log.txt
251
252 feature {NONE} -- Handlers
253
254 report_batch_assignment
255 require
256 last_request_attached: last_request /= Void
257 last_request_is_batch_assignment: is_last_request_batch_assignment
258 local
259 l_receivers: SPECIAL [TUPLE [var_with_uuid: STRING; var: ITP_VARIABLE]]
260 l_serialized_objects: SPECIAL[STRING]
261 l_objects_seri: STRING
262 l_uuid_objects_mapping: HASH_TABLE [HASH_TABLE[ANY, INTEGER], STRING]
263 i, l_index, l_count: INTEGER
264 l_var_with_uuid: STRING
265 l_var_name, l_uuid: STRING
266 l_var_index, l_at_sign: INTEGER
267 l_variable: ITP_VARIABLE
268 l_object: ANY
269 l_retried: BOOLEAN
270 b: BOOLEAN
271 do
272 if not l_retried then
273 if attached {TUPLE [receivers: SPECIAL [TUPLE [var_with_uuid: STRING; var: ITP_VARIABLE]]; serialized_objects: SPECIAL[STRING]]} last_request as lv_operands then
274 log_message (once "report batch assignment start%N")
275
276 -- Deserialize objects.
277 l_serialized_objects := lv_operands.serialized_objects
278 -- check even_count: l_serialized_objects.count \\ 2 = 0 end
279 from
280 create l_uuid_objects_mapping.make (l_serialized_objects.count)
281 l_uuid_objects_mapping.compare_objects
282 l_index := 0
283 until
284 l_index >= l_serialized_objects.count
285 loop
286 l_uuid := l_serialized_objects.at (l_index)
287 l_objects_seri := l_serialized_objects.at (l_index + 1)
288
289 check attached {HASH_TABLE [ANY, INTEGER_32]} deserialized_variable_table (ascii_string_as_array (l_objects_seri)) as lv_mapping then
290 l_uuid_objects_mapping.put (lv_mapping, l_uuid)
291 end
292 l_index := l_index + 2
293 end
294
295 -- Store objects into variables.
296 from
297 l_receivers := lv_operands.receivers
298 l_index := 0
299 until
300 l_index >= l_receivers.count
301 loop
302 l_variable := l_receivers.at (l_index).var
303 l_var_with_uuid := l_receivers.at (l_index).var_with_uuid
304
305 l_at_sign := l_var_with_uuid.index_of ('@', 1)
306 -- check found_at: l_at_sign > 0 end
307 l_var_name := l_var_with_uuid.substring (1, l_at_sign - 1)
308 l_uuid := l_var_with_uuid.substring (l_at_sign + 1, l_var_with_uuid.count)
309 l_var_index := l_var_name.substring (3, l_var_name.count.to_integer).to_integer
310 -- check var_with_uuid_exists: l_uuid_objects_mapping.has (l_uuid) and then l_uuid_objects_mapping.item (l_uuid).has (l_var_index) end
311 l_object := l_uuid_objects_mapping.item (l_uuid).item (l_var_index)
312
313 store_variable_at_index (l_object, l_variable.index)
314
315 -- Uncomment for debugging
316 -- b := {ISE_RUNTIME}.check_assert (False)
317 -- if l_object /= Void then
318 -- log_message ("Batch assign: " + {ITP_SHARED_CONSTANTS}.variable_name_prefix + l_variable.index.out + ": " + l_object.generating_type.name + "%N")
319 -- else
320 -- log_message ("Batch assign: " + {ITP_SHARED_CONSTANTS}.variable_name_prefix + l_variable.index.out + ": Void%N")
321 -- end
322 -- b := {ISE_RUNTIME}.check_assert (b)
323
324 l_index := l_index + 1
325 end
326 log_message (once "report batch assignment end%N")
327 else
328 report_error (batch_assignment_error + "[receiving request argument objects failed]%N")
329 end
330 else
331 report_error (batch_assignment_error + "[exception happend]%N")
332 end
333
334 -- Send response to the proxy.
335 refresh_last_response_flag
336 last_response := [0, Void, Void, output_buffer, error_buffer]
337 send_response_to_socket
338 rescue
339 log_message (exception_trace + "%N")
340 l_retried := True
341 retry
342 end
343
344
345 report_type_request
346 require
347 last_request_attached: last_request /= Void
348 last_request_is_type_request: last_request_type = type_request_flag
349 local
350 b: BOOLEAN
351 l_index: INTEGER
352 l_value: detachable ANY
353 l_store: like store
354 l_type: STRING
355 l_generating_type: STRING
356 do
357 if attached {STRING} last_request as l_obj_index then
358 log_message (once "report_type_request start%N")
359 l_index := l_obj_index.to_integer
360 l_store := store
361 if l_store.is_variable_defined (l_index) then
362 l_value := l_store.variable_value (l_index)
363 if l_value = Void then
364 create l_type.make (4)
365 l_generating_type := none_type_name
366 else
367 create l_type.make (64)
368
369 -- We disable assertion checking here because `l_value'.`generating_type' is
370 -- a qualified call, if `l_value' has invariant violation, an exception will be thrown,
371 -- causing the interpreter to generate an error. The invariant of `l_value' was violated
372 -- indirectly by other objects.
373 -- In this case, we don't want a failure here, we want a failure when we actually
374 -- try to use `l_value'.
375 b := {ISE_RUNTIME}.check_assert (False)
376 l_generating_type := l_value.generating_type
377 b := {ISE_RUNTIME}.check_assert (b)
378 end
379 l_type.append (l_generating_type)
380 l_type.append_character ('%N')
381 l_type.append (value_of_object (l_value, l_generating_type))
382 print_line_and_flush (l_type)
383 else
384 report_error (once "Variable `v_" + l_index.out + "' not defined.")
385 end
386 log_message (once "report_type_request end%N")
387 else
388 report_error (invalid_request_format_error)
389 end
390
391 -- Send response to the proxy.
392 refresh_last_response_flag
393 last_response := [0, Void, Void, output_buffer, error_buffer]
394 send_response_to_socket
395 end
396
397 report_quit_request
398 do
399 should_quit := True
400 end
401
402 report_start_request
403 do
404 end
405
406 report_execute_request
407 -- Report execute request.
408 require
409 last_request_attached: last_request /= Void
410 last_request_is_execute_request: last_request_type = execute_request_flag or last_request_type = execute_agent_creation_flag
411 local
412 l_bcode: detachable STRING
413 l_cstring: C_STRING
414 l_predicate_results: TUPLE [INTEGER, detachable like evaluated_predicate_results]
415 i: INTEGER
416 l_object_summary: ARRAYED_LIST [STRING]
417 l_upper: INTEGER
418 l_lower: INTEGER
419 l_canned_objects: STRING
420 l_serializer: like test_case_serializer
421 j: INTEGER
422 do
423 is_failing_test_case := False
424 last_test_case_serialization := Void
425 if attached {TUPLE [l_byte_code: STRING; l_feat_name: detachable STRING; l_data: detachable ANY]} last_request as l_last_request then
426 l_bcode := l_last_request.l_byte_code
427 if l_bcode = Void then
428 report_error (byte_code_not_found_error)
429 elseif l_bcode.count = 0 then
430 report_error (byte_code_length_error)
431 else
432 if l_last_request.l_feat_name /= Void then
433 log_message (once "report_execute_request start: " + l_last_request.l_feat_name + "%N")
434 else
435 log_message (once "report_execute_request start%N")
436 end
437
438 -- Inject received byte-code into byte-code array of Current process.
439 create l_cstring.make (l_bcode)
440 override_byte_code_of_body (
441 byte_code_feature_body_id,
442 byte_code_feature_pattern_id,
443 l_cstring.item,
444 l_bcode.count)
445
446 -- Test case serialization: retrieve pre-TC state.
447 if is_test_case_serialization_enabled
448 and then not is_test_case_agent_creation
449 then
450 retrieve_test_case_prestate (l_last_request.l_data)
451 end
452
453 -- Run the feature with newly injected byte-code.
454 -- if variable_at_index (3) = Void then
455 -- log_message ("Error, Error: v_3 is Void.%N")
456 -- end
457 execute_protected
458 log_message (once "report_execute_request end%N")
459
460 -- Evaluate relevant predicates.
461 if is_last_protected_execution_successful and then is_predicate_evaluation_enabled then
462 if attached {detachable ARRAY [detachable ANY]} l_last_request.l_data as l_extra_data then
463 if attached {TUPLE [feature_id: INTEGER; operands: SPECIAL [INTEGER]]} l_extra_data.item (extra_data_index_precondition_satisfaction) as l_feature_data then
464 -- Uncomment the following section for debugging purpose. 2.10.2010 Jasonw
465 -- log_message ("Feature id: " + l_feature_data.feature_id.out + "%N")
466 -- from
467 -- j := 0
468 -- until
469 -- j = l_feature_data.operands.count
470 -- loop
471 -- log_message ("Object id: " + l_feature_data.operands.item (j).out + ", ")
472 -- j := j + 1
473 -- end
474 -- log_message ("%N")
475 l_predicate_results := [l_feature_data.feature_id, evaluated_predicate_results (l_feature_data.feature_id, l_feature_data.operands)]
476 else
477 l_predicate_results := Void
478 end
479 end
480 end
481
482 -- Test case serialization.
483 if is_test_case_serialization_enabled
484 and then not is_test_case_agent_creation
485 then
486 retrieve_post_test_case_state
487 log_test_case_serialization
488 end
489 end
490 else
491 report_error (invalid_request_format_error)
492 end
493
494 -- Send response to the proxy.
495 refresh_last_response_flag
496 last_response := [invariant_violating_object_index, l_predicate_results, last_test_case_serialization, output_buffer, error_buffer]
497 send_response_to_socket
498 end
499
500 refresh_last_response_flag
501 -- Refresh the value of `last_response_flag' according to current status.
502 do
503 if has_error then
504 last_response_flag := internal_error_respones_flag
505 elseif is_last_invariant_violated then
506 last_response_flag := invariant_violation_on_entry_response_flag
507 else
508 last_response_flag := normal_response_flag
509 end
510 end
511
512 feature {NONE} -- Error Reporting
513
514 report_error (a_reason: STRING)
515 require
516 a_reason_not_void: a_reason /= Void
517 a_reason_not_empty: not a_reason.is_empty
518 do
519 error_buffer.append (once "error: " + a_reason + once "%N")
520 last_response_flag := internal_error_respones_flag
521 has_error := True
522 log_message (error_buffer)
523 ensure
524 has_error: has_error
525 end
526
527 log_internal_error (a_reason: STRING)
528 -- Put `a_reason' in log file.
529 require
530 a_reason_attached: a_reason /= Void
531 not_a_reason_is_empty: not a_reason.is_empty
532 do
533 if should_generate_log then
534 log_file.put_string (once "<error type='internal'>%N")
535 log_file.put_string (once "%T<reason>%N<![CDATA[%N")
536 log_file.put_string (a_reason)
537 log_file.put_string (once "]]>%N</reason>%N")
538 log_file.put_string (once "</error>%N")
539 end
540 end
541
542 feature {ITP_TEST_CASE_SERIALIZER} -- Logging
543
544 log_file: PLAIN_TEXT_FILE
545 -- Log file
546
547 log_instance (an_object: detachable ANY)
548 -- Log an XML representation of `an_object' to `log_file'.
549 do
550 log_message (once "<instance<![CDATA[%N")
551 if an_object = Void then
552 log_message (once "Void%N")
553 else
554 log_message (an_object.tagged_out)
555 end
556 log_message (once "]]>%N</instance>%N")
557 end
558
559 log_message (a_message: STRING)
560 -- Log message `a_messgae' to `log_message'.
561 require
562 a_message_not_void: a_message /= Void
563 do
564 if should_generate_log then
565 log_file.put_string (a_message)
566 end
567 end
568
569 report_trace
570 -- Report trace information into `error_buffer'.
571 require
572 -- has_exception: An exception happened before
573 local
574 l_buffer: like error_buffer
575 l_exception_code: INTEGER
576 l_recipient: like recipient_name
577 l_recipient_class_name: like class_name
578 l_tag: like tag_name
579 l_trace: like exception_trace
580 l_meaning: like meaning
581 l_line_number: INTEGER
582 do
583 -- Gather exception information.
584 -- l_exception_code := exception
585 -- l_tag := tag_name
586 -- l_recipient := recipient_name
587 -- l_recipient_class_name := class_name
588
589 l_exception_code := original_exception
590 l_tag := original_tag_name
591 if l_tag = Void then
592 l_tag := "noname"
593 end
594 l_recipient := original_recipient_name
595 l_recipient_class_name := original_class_name
596 if attached {EXCEPTION} exception_manager.last_exception as l_except then
597 if attached {EXCEPTION} l_except.cause as l_cause then
598 l_line_number := l_cause.line_number
599 end
600 end
601 last_fault_id := l_recipient_class_name + "." + l_recipient + "." + l_exception_code.out + "." + l_tag
602
603 l_trace := exception_trace
604
605 l_meaning := meaning (l_exception_code)
606 check l_trace /= Void end
607
608 if l_meaning = Void then
609 l_meaning := ""
610 end
611 if l_recipient = Void then
612 l_recipient := ""
613 end
614 check l_class_name_not_void: l_recipient_class_name /= Void end
615 if l_tag = Void then
616 l_tag := ""
617 end
618
619 -- Print exception into buffer which will be transfered through socket to proxy.
620 l_buffer := error_buffer
621 l_buffer.append (l_exception_code.out)
622 l_buffer.append_character ('%N')
623 l_buffer.append (l_recipient)
624 l_buffer.append_character ('%N')
625 l_buffer.append (l_recipient_class_name)
626 l_buffer.append_character ('%N')
627 l_buffer.append (l_tag)
628 l_buffer.append_character ('%N')
629 l_buffer.append (is_last_invariant_violated.out)
630 l_buffer.append_character ('%N')
631 l_buffer.append (l_trace)
632
633 -- Store exception into log file.
634 log_message (once "<call_result type='exception'>%N")
635 log_message (once "%T<meaning value='" + l_meaning + once "'/>%N")
636 log_message (once "%T<tag value='" + l_tag + once "'/>%N")
637 log_message (once "%T<recipient value='" + l_recipient + once "'/>%N")
638 log_message (once "%T<class value='" + l_recipient_class_name + once "'>%N")
639 log_message (once "%T<invariant violation on entry='" + is_last_invariant_violated.out + once "'>%N")
640 log_message (once "%T<exception_trace>%N<![CDATA[%N")
641 log_message (l_trace)
642 log_message (once "]]>%N</exception_trace>%N")
643 log_message (once "</call_result>%N")
644 end
645
646 last_fault_id: detachable STRING
647 -- Id of the last detected fault
648 -- Only have correct value if is_failing_test_case is True
649
650 feature -- IO Buffer
651
652 output_buffer: STRING_8
653 -- Buffer used to store standard output from Current process
654 -- Fixme: Should store standard error also, but due to an implementation
655 -- limitation in STD_FILES, we cannot redirect standard error to a buffer.
656 -- So stderr will be ignored for the moment. Jason 2008.10.18
657
658 error_buffer: STRING
659 -- Buffer to store error information (either interpreter error or exception trace from testee feature)
660 -- Note: Error here does not mean standard error from testee feature, stderr error should be handled by
661 -- `output_buffer'.
662
663 wipe_out_buffer
664 -- Clear `output_buffer' and `error_buffer'.
665 do
666 output_buffer.wipe_out
667 error_buffer.wipe_out
668 ensure
669 output_buffer_cleared: output_buffer.is_empty
670 error_buffer_cleared: error_buffer.is_empty
671 end
672
673 buffer_size: INTEGER = 4096
674 -- Size in byte for `output_buffer'
675
676 feature {NONE} -- Socket IPC
677
678 socket: NETWORK_STREAM_SOCKET
679 -- Socket used for communitation between proxy and current interpreter
680
681 last_request_type: NATURAL_32
682 -- Type of the last request retrieved by `retrieve_request'.
683
684 last_request: detachable ANY
685 -- Last received request by `retrieve_request'
686 -- `flag' indicates request type,
687 -- `data' stores data needed for that reques type.
688
689 last_response_flag: NATURAL_32
690 -- Flag indicating the status of the response
691 -- See {ITP_SHARED_CONSTANTS} for valid values
692
693 last_response: detachable ANY
694 -- Last response to be sent back to the proxy
695
696 retrieve_request
697 -- Retrieve request from proxy and store it in `last_request'.
698 -- Blocking if no request is received.
699 -- Close socket on error.
700 require
701 socket_attached: socket /= Void
702 socket_open: socket.is_open_read
703 local
704 l_retried: BOOLEAN
705 do
706 last_request := Void
707 last_response := Void
708 is_last_invariant_violated := False
709
710 if not l_retried then
711 -- Get request from proxy through `socket'.
712 -- This will block Current process.
713 socket.read_natural_32
714 last_request_type := socket.last_natural_32
715
716 if attached {like last_request} socket.retrieved as l_request then
717 last_request := l_request
718 end
719 end
720 rescue
721 l_retried := True
722 last_request := Void
723 if not socket.is_closed then
724 socket.close
725 end
726 retry
727 end
728
729 send_response_to_socket
730 -- Send response stored in `output_buffer' and `error_buffer' into `socket'.
731 -- If error occurs, close `socket'.
732 local
733 l_retried: BOOLEAN
734 l_last_response: like last_response
735 do
736 if not l_retried then
737 socket.put_natural_32 (last_response_flag)
738 l_last_response := last_response
739 check l_last_response /= Void end
740 socket.independent_store (l_last_response)
741 end
742 rescue
743 l_retried := True
744 has_error := True
745 socket.close
746 retry
747 end
748
749 print_line_and_flush (a_text: STRING)
750 -- Print `a_text' followed by a newline and flush output stream.
751 require
752 a_text_not_void: a_text /= Void
753 do
754 output_buffer.append (a_text)
755 output_buffer.append_character ('%N')
756 end
757
758 feature {NONE} -- Parsing
759
760 parse
761 -- Parse input and call corresponding handler routines (`report_*').
762 require
763 not_has_error: not has_error
764 do
765 if is_request_type_valid (last_request_type) then
766 if last_request = Void then
767 report_error (once "Received data is not recognized as a request.")
768 else
769 is_test_case_agent_creation := False
770 inspect
771 last_request_type
772 when execute_request_flag then
773 report_execute_request
774 when execute_agent_creation_flag then
775 is_test_case_agent_creation := True
776 report_execute_request
777
778 when execute_batch_assignment_flag then
779 report_batch_assignment
780
781 when type_request_flag then
782 report_type_request
783
784 when start_request_flag then
785 report_start_request
786
787 when object_state_request_flag then
788 report_object_state_request
789
790 when precondition_evaluation_request_flag then
791 report_error (invalid_request_type_error + once " Type code: " + last_request_type.out)
792
793 when predicate_evaluation_request_flag then
794 report_predicate_evaluate_request
795
796 when quit_request_flag then
797 report_quit_request
798 end
799 end
800 else
801 report_error (invalid_request_type_error + once " Type code: " + last_request_type.out)
802 end
803 end
804
805 feature {ITP_TEST_CASE_SERIALIZER} -- Object pool
806
807 store: ITP_STORE
808 -- Object store
809
810 feature {NONE} -- Byte code
811
812 byte_code_feature_body_id: INTEGER
813 -- ID for feature whose byte-code is to be injected
814
815 byte_code_feature_pattern_id: INTEGER
816 -- Pattern ID for feature whose byte-code is to be injected
817
818 execute_protected
819 -- Execute `procedure' in a protected way.
820 local
821 failed: BOOLEAN
822 fault_id: STRING
823 do
824 is_last_protected_execution_successful := False
825 if not failed then
826 is_failing_test_case := False
827 is_invalid_test_case := False
828 execute_byte_code
829 is_last_protected_execution_successful := True
830 end
831 rescue
832 failed := True
833 report_trace
834
835 -- Book keeps found faults.
836 if not is_last_invariant_violated then
837 if (original_recipient_name.is_equal (once "execute_byte_code") and then exception = {EXCEP_CONST}.Precondition) then
838 is_invalid_test_case := True
839 is_failing_test_case := False
840 else
841 is_invalid_test_case := False
842 is_failing_test_case := True
843 end
844 else
845 is_invalid_test_case := True
846 is_failing_test_case := False
847 end
848 -- if exception = Class_invariant then
849 -- -- A class invariant cannot be recovered from since we
850 -- -- don't know how many and what objects are now invalid
851 -- should_quit := True
852 -- end
853 retry
854 end
855
856 execute_byte_code
857 -- Execute test case
858 -- The test case will be written as byte-code.
859 local
860 v_1: detachable STRING
861 do
862 v_1 := Void
863 end
864
865 store_variable_at_index (a_object: ANY; a_index: INTEGER)
866 -- Store `a_object' at `a_index' in `store'.
867 do
868 store.assign_value (a_object, a_index)
869 end
870
871 main_loop
872 -- Main loop
873 do
874 from
875 until
876 should_quit or else socket.is_closed
877 loop
878 wipe_out_buffer
879 retrieve_request
880 if not has_error then
881 parse
882 end
883 has_error := False
884 end
885 end
886
887 feature{NONE} -- Error message
888
889 invalid_request_format_error: STRING = "Invalid request format."
890
891 byte_code_not_found_error: STRING = "No byte-code is found in request."
892
893 byte_code_length_error: STRING = "Length of retrieved byte-code is not the same as specified in request."
894
895 invalid_request_type_error: STRING = "Request type is invalid."
896
897 batch_assignment_error: STRING = "Batch assignment data invalid "
898
899 feature{ITP_TEST_CASE_SERIALIZER} -- Invariant checking
900
901 is_last_invariant_violated: BOOLEAN
902 -- Is the class invariant violated when `check_invariant' is invoked
903 -- the last time?
904
905 is_failing_test_case: BOOLEAN
906 -- Is current test case failing, meaning that it reveals a fault?
907
908 is_invalid_test_case: BOOLEAN
909 -- Is current test case invalid, meaning that it violates the feature's precondition?
910
911 feature{NONE} -- Invariant checking
912
913 invariant_violating_object_index: INTEGER
914 -- Index of the object which violates it class invariant
915
916 check_invariant (a_index: INTEGER; o: detachable ANY)
917 -- Check if the class invariant `o' with index `a_index' is satisfied.
918 -- If not satisfied, set `is_last_invariant_violated' to True
919 -- and raise the exception.
920 -- If satisfied, set `is_last_invariant_violated' to False.
921 -- if `o' is detached, set `is_last_invariant_violated' to False and do nothing.
922 require
923 a_index_positive: a_index > 0
924 do
925 if o /= Void then
926 log_message ("Check invariant: " + variable_name (a_index) + ": " + o.generating_type.name + "%N")
927 else
928 log_message ("Check invariant: " + variable_name (a_index) + ": Void%N")
929 end
930 if attached {ANY} o as l_obj then
931 l_obj.do_nothing
932 end
933 invariant_violating_object_index := 0
934 rescue
935 is_last_invariant_violated := True
936 invariant_violating_object_index := a_index
937 log_message ("Check invariant: " + variable_name (a_index) + " violates its class invariants.%N")
938 end
939
940 variable_name (a_index: INTEGER): STRING
941 -- Variable name with index `a_index'
942 do
943 Result := {ITP_SHARED_CONSTANTS}.variable_name_prefix + a_index.out
944 end
945
946 feature -- Object state checking
947
948 initialize_query_value_holders is
949 -- Initialize `query_values' and `query_status'.
950 do
951 if query_values = Void then
952 create query_values.make (20)
953 create query_value_hash_list.make
954 else
955 query_values.wipe_out
956 query_value_hash_list.wipe_out
957 end
958 end
959
960 report_object_state_request is
961 -- Report an object state request.
962 local
963 o: detachable ANY
964 l_retried: BOOLEAN
965 l_bcode: STRING
966 l_cstring: C_STRING
967 do
968 if not l_retried then
969 output_buffer.wipe_out
970 error_buffer.wipe_out
971 if attached {TUPLE [pre_state_byte_code: STRING; post_state_byte_code: detachable STRING]} last_request as l_request then
972 -- Initialize query result storage
973 initialize_query_value_holders
974
975 -- Load byte-code.
976 l_bcode := l_request.pre_state_byte_code
977
978 if l_bcode.count = 0 then
979 report_error (byte_code_length_error)
980 else
981 if l_request.post_state_byte_code /= Void and then is_test_case_serialization_enabled and then is_post_state_serialized then
982 post_state_retrieveal_byte_code := l_request.post_state_byte_code
983 else
984 post_state_retrieveal_byte_code := Void
985 end
986 log_message (once "report_object_state_request start%N")
987
988 -- Inject received byte-code into byte-code array of Current process.
989 create l_cstring.make (l_bcode)
990 override_byte_code_of_body (
991 byte_code_feature_body_id,
992 byte_code_feature_pattern_id,
993 l_cstring.item,
994 l_bcode.count)
995
996 -- Run the feature with newly injected byte-code.
997 last_response_flag := normal_response_flag
998 execute_protected
999 log_message (once "report_object_state_request end%N")
1000 end
1001 last_response := [query_values, output_buffer, error_buffer]
1002 refresh_last_response_flag
1003 send_response_to_socket
1004 else
1005 report_error (invalid_object_state_request)
1006 last_response := [Void, Void, output_buffer, error_buffer]
1007 refresh_last_response_flag
1008 send_response_to_socket
1009 end
1010 end
1011 rescue
1012 l_retried := True
1013 last_response := [Void, Void, output_buffer, error_buffer]
1014 refresh_last_response_flag
1015 send_response_to_socket
1016 retry
1017 end
1018
1019 retrieve_post_object_state
1020 -- Retrieve post-execution object states by executing byte-code
1021 -- stored in `post_state_retrieval_byte_code'.
1022 local
1023 l_cstring: C_STRING
1024 do
1025 initialize_query_value_holders
1026 if attached {STRING} post_state_retrieveal_byte_code as l_byte_code then
1027 create l_cstring.make (l_byte_code)
1028 override_byte_code_of_body (
1029 byte_code_feature_body_id,
1030 byte_code_feature_pattern_id,
1031 l_cstring.item,
1032 l_byte_code.count)
1033
1034 -- Run the feature with newly injected byte-code.
1035 execute_protected
1036 end
1037 end
1038
1039 invalid_object_state_request: STRING = "Invalid object state request."
1040 -- Error message for invalid object state request
1041
1042 invalid_predicate_evaluation_request: STRING = "Invalid predicate evaluation request."
1043
1044 query_values: HASH_TABLE [STRING, STRING]
1045 -- Table to store string representation of query values
1046 -- Key is query name, value is the value of that query
1047
1048 query_value_hash_list: LINKED_LIST [INTEGER]
1049 -- List of `query_values'.
1050 -- The first element is the hash code of the value of the first evaluated query in an object state request,
1051 -- the second element is the hash code of the value of the second evaluated query in an object state request, and so on.
1052
1053 record_attribute_value (a_query_name: STRING; a_value: detachable ANY)
1054 -- Record the query named `a_query_name' to have `a_value' into `query_values'.
1055 local
1056 l_internal: like internal
1057 l_type: INTEGER
1058 l_value: STRING
1059 do
1060 if a_value = Void then
1061 query_values.put (void_value, a_query_name)
1062 else
1063 l_internal := internal
1064 if special_type_mapping.has (l_internal.dynamic_type (a_value)) then
1065 l_value := a_value.out
1066 query_values.put (l_value, a_query_name)
1067 query_value_hash_list.extend (l_value.hash_code)
1068 else
1069 l_value := ($a_value).out
1070 query_values.put (l_value, a_query_name)
1071 query_value_hash_list.extend (l_value.hash_code)
1072 end
1073 end
1074 end
1075
1076 record_integer_function_value (a_query_name: STRING; a_query: FUNCTION [ANY, TUPLE [INTEGER], detachable ANY]; a_argument: INTEGER)
1077 -- Evaluate the query specified by `a_query' and record its value into `query_values'
1078 -- under the name `a_query_name'.
1079 -- `a_query' has an argument, which is given by `a_argument'.
1080 require
1081 a_query_attached: a_query /= Void
1082 local
1083 l_retried: BOOLEAN
1084 l_result: detachable ANY
1085 do
1086 if not l_retried then
1087 l_result := a_query.item ([a_argument])
1088 record_evaluated_value (a_query_name, l_result)
1089 end
1090 rescue
1091 query_values.put (nonsensical_value, a_query_name)
1092 query_value_hash_list.extend (nonsensical_value.hash_code)
1093 log_query_evaluation_failure (a_query_name, a_argument, exception_trace)
1094 l_retried := True
1095 retry
1096 end
1097
1098 record_boolean_function_value (a_query_name: STRING; a_query: FUNCTION [ANY, TUPLE [BOOLEAN], detachable ANY]; a_argument: BOOLEAN)
1099 -- Evaluate the query specified by `a_query' and record its value into `query_values'
1100 -- under the name `a_query_name'.
1101 -- `a_query' has an argument, which is given by `a_argument'.
1102 require
1103 a_query_attached: a_query /= Void
1104 local
1105 l_retried: BOOLEAN
1106 l_result: detachable ANY
1107 do
1108 if not l_retried then
1109 l_result := a_query.item ([a_argument])
1110 record_evaluated_value (a_query_name, l_result)
1111 end
1112 rescue
1113 query_values.put (nonsensical_value, a_query_name)
1114 query_value_hash_list.extend (nonsensical_value.hash_code)
1115 log_query_evaluation_failure (a_query_name, a_argument, exception_trace)
1116 l_retried := True
1117 retry
1118 end
1119
1120 record_argumented_function_value (a_query_name: STRING; a_query: FUNCTION [ANY, TUPLE [detachable ANY], detachable ANY]; a_argument: detachable ANY)
1121 -- Evaluate the query specified by `a_query' and record its value into `query_values'
1122 -- under the name `a_query_name'.
1123 -- `a_query' has an argument, which is given by `a_argument'.
1124 require
1125 a_query_attached: a_query /= Void
1126 local
1127 l_retried: BOOLEAN
1128 l_result: detachable ANY
1129 do
1130 if not l_retried then
1131 l_result := a_query.item ([a_argument])
1132 record_evaluated_value (a_query_name, l_result)
1133 end
1134 rescue
1135 query_values.put (nonsensical_value, a_query_name)
1136 query_value_hash_list.extend (nonsensical_value.hash_code)
1137 log_query_evaluation_failure (a_query_name, a_argument, exception_trace)
1138 l_retried := True
1139 retry
1140 end
1141
1142 record_function_value (a_query_name: STRING; a_query: FUNCTION [ANY, TUPLE, detachable ANY])
1143 -- Evaluate the query specified by `a_query' and record its value into `query_values'
1144 -- under the name `a_query_name'.
1145 require
1146 a_query_attached: a_query /= Void
1147 local
1148 l_retried: BOOLEAN
1149 l_result: detachable ANY
1150 do
1151 if not l_retried then
1152 l_result := a_query.item (Void)
1153 record_evaluated_value (a_query_name, l_result)
1154 end
1155 rescue
1156 query_values.put (nonsensical_value, a_query_name)
1157 query_value_hash_list.extend (nonsensical_value.hash_code)
1158 log_query_evaluation_failure (a_query_name, Void, exception_trace)
1159 l_retried := True
1160 retry
1161 end
1162
1163 record_object_equality_comparison_value (a_query_name: STRING; a_obj1: detachable ANY; a_obj2: detachable ANY)
1164 -- Record the value of the object equality comparison between `a_obj1' and `a_obj2',
1165 -- and store result in `query_values'.
1166 require
1167 a_query_attached: a_query_name /= Void
1168 local
1169 l_retried: BOOLEAN
1170 l_result: BOOLEAN
1171 l_agent: FUNCTION [ANY, TUPLE [detachable ANY, detachable ANY], BOOLEAN]
1172 do
1173 if not l_retried then
1174 l_agent := agent is_object_equal
1175 l_result := l_agent.item ([a_obj1, a_obj2])
1176 record_evaluated_value (a_query_name, l_result)
1177 end
1178 rescue
1179 query_values.put (nonsensical_value, a_query_name)
1180 query_value_hash_list.extend (nonsensical_value.hash_code)
1181 log_query_evaluation_failure (a_query_name, Void, exception_trace)
1182 l_retried := True
1183 retry
1184 end
1185
1186 record_reference_equality_comparison_value (a_query_name: STRING; a_obj1: detachable ANY; a_obj2: detachable ANY)
1187 -- Record the value of the reference equality comparison between `a_obj1' and `a_obj2',
1188 -- and store result in `query_values'.
1189 require
1190 a_query_attached: a_query_name /= Void
1191 local
1192 l_retried: BOOLEAN
1193 l_result: BOOLEAN
1194 l_agent: FUNCTION [ANY, TUPLE [detachable ANY, detachable ANY], BOOLEAN]
1195 do
1196 if not l_retried then
1197 l_agent := agent is_reference_equal
1198 l_result := l_agent.item ([a_obj1, a_obj2])
1199 record_evaluated_value (a_query_name, l_result)
1200 end
1201 rescue
1202 query_values.put (nonsensical_value, a_query_name)
1203 query_value_hash_list.extend (nonsensical_value.hash_code)
1204 log_query_evaluation_failure (a_query_name, Void, exception_trace)
1205 l_retried := True
1206 retry
1207 end
1208
1209 is_object_equal (a_obj1: detachable ANY; a_obj2: detachable ANY): BOOLEAN
1210 -- Is `a_obj1' object equal to `a_obj2'?
1211 do
1212 Result := a_obj1 ~ a_obj2
1213 end
1214
1215 is_reference_equal (a_obj1: detachable ANY; a_obj2: detachable ANY): BOOLEAN
1216 -- Is `a_obj1' reference equal to `a_obj2'?
1217 do
1218 Result := a_obj1 = a_obj2
1219 end
1220
1221 log_query_evaluation_failure (a_query_name: STRING; a_argument: detachable ANY; a_trace: STRING)
1222 -- Log that the evaluation of `a_query_name' with `a_argument' failed with trace `a_trace'.
1223 do
1224 log_message ("-----------------------------------------------%N")
1225 log_message (a_query_name + "%N")
1226 if a_argument /= Void then
1227 log_message (a_argument.generating_type + "%N")
1228 else
1229 log_message ("argument is Void.%N")
1230 end
1231 if a_trace /= Void then
1232 log_message (exception_trace)
1233 end
1234 end
1235
1236 record_void_value (a_variable_index: INTEGER)
1237 -- Record that object with `a_variable_index' is Void into `query_values'.
1238 do
1239 query_values.put (void_value, object_name (a_variable_index))
1240 query_value_hash_list.extend (void_value.hash_code)
1241 log_message (variable_name_prefix + a_variable_index.out + " is void.%N")
1242 end
1243
1244 record_basic_value (a_variable_index: INTEGER; a_value: STRING)
1245 -- Record that object with `a_variable_index' has value `a_value' into `query_values'.
1246 -- That object must be of primitive type.
1247 do
1248 query_values.put (a_value, object_name (a_variable_index))
1249 query_value_hash_list.extend (a_value.hash_code)
1250 log_message (variable_name_prefix + a_variable_index.out + " is " + a_value + "%N")
1251 end
1252
1253 record_invariant_violating_value (a_variable_index: INTEGER)
1254 -- Record that object with `a_variable_index' voilates its class invariants in `query_values'.
1255 do
1256 query_values.put (invariant_violation_value, object_name (a_variable_index))
1257 query_value_hash_list.extend (invariant_violation_value.hash_code)
1258 end
1259
1260 record_evaluated_value (a_query_name: STRING; a_value: detachable ANY)
1261 -- Record evaluated `a_value' for `a_query_name'.
1262 local
1263 l_retried: BOOLEAN
1264 l_result: detachable ANY
1265 l_internal: like internal
1266 l_value: STRING
1267 do
1268 if a_value = Void then
1269 query_values.put (void_value, a_query_name)
1270 else
1271 l_internal := internal
1272 if special_type_mapping.has (l_internal.dynamic_type (a_value)) then
1273 l_value := a_value.out
1274 query_values.put (l_value, a_query_name)
1275 query_value_hash_list.extend (l_value.hash_code)
1276 else
1277 l_value := ($a_value).out
1278
1279 query_values.put (l_value, a_query_name)
1280 query_value_hash_list.extend (reference_value.hash_code)
1281 end
1282 end
1283 end
1284
1285 object_name (a_index: INTEGER): STRING
1286 -- Name of object with `a_index'
1287 do
1288 create Result.make (5)
1289 Result.append (variable_name_prefix)
1290 Result.append (a_index.out)
1291 end
1292
1293 internal: INTERNAL
1294 -- Internal to get types of an object
1295
1296 post_state_retrieveal_byte_code: detachable STRING
1297 -- Byte code used to retrieve post-execute object states
1298
1299 hash_table_type: TYPE [HASH_TABLE [INTEGER, INTEGER]]
1300 -- Type anchor
1301
1302 feature -- Function types
1303
1304 function0: FUNCTION [ANY, TUPLE, INTEGER]
1305 function1: FUNCTION [ANY, TUPLE, INTEGER_8]
1306 function2: FUNCTION [ANY, TUPLE, INTEGER_16]
1307 function3: FUNCTION [ANY, TUPLE, INTEGER_64]
1308 function4: FUNCTION [ANY, TUPLE, NATURAL]
1309 function5: FUNCTION [ANY, TUPLE, NATURAL_8]
1310 function6: FUNCTION [ANY, TUPLE, NATURAL_16]
1311 function7: FUNCTION [ANY, TUPLE, NATURAL_64]
1312 function8: FUNCTION [ANY, TUPLE, REAL_32]
1313 function9: FUNCTION [ANY, TUPLE, REAL_64]
1314 function10: FUNCTION [ANY, TUPLE, BOOLEAN]
1315 function11: FUNCTION [ANY, TUPLE, CHARACTER]
1316 function12: FUNCTION [ANY, TUPLE, CHARACTER_32]
1317 function13: FUNCTION [ANY, TUPLE, POINTER]
1318 function14: FUNCTION [ANY, TUPLE, ANY]
1319
1320 -- function20: FUNCTION [ANY, TUPLE [INTEGER], INTEGER]
1321 -- function21: FUNCTION [ANY, TUPLE [INTEGER], INTEGER_8]
1322 -- function22: FUNCTION [ANY, TUPLE [INTEGER], INTEGER_16]
1323 -- function23: FUNCTION [ANY, TUPLE [INTEGER], INTEGER_64]
1324 -- function24: FUNCTION [ANY, TUPLE [INTEGER], NATURAL]
1325 -- function25: FUNCTION [ANY, TUPLE [INTEGER], NATURAL_8]
1326 -- function26: FUNCTION [ANY, TUPLE [INTEGER], NATURAL_16]
1327 -- function27: FUNCTION [ANY, TUPLE [INTEGER], NATURAL_64]
1328 -- function28: FUNCTION [ANY, TUPLE [INTEGER], REAL_32]
1329 -- function29: FUNCTION [ANY, TUPLE [INTEGER], REAL_64]
1330 -- function30: FUNCTION [ANY, TUPLE [INTEGER], BOOLEAN]
1331 -- function31: FUNCTION [ANY, TUPLE [INTEGER], CHARACTER]
1332 -- function32: FUNCTION [ANY, TUPLE [INTEGER], CHARACTER_32]
1333 -- function33: FUNCTION [ANY, TUPLE [INTEGER], POINTER]
1334 -- function34: FUNCTION [ANY, TUPLE [INTEGER], ANY]
1335
1336 -- function40: FUNCTION [ANY, TUPLE [BOOLEAN], INTEGER]
1337 -- function41: FUNCTION [ANY, TUPLE [BOOLEAN], INTEGER_8]
1338 -- function42: FUNCTION [ANY, TUPLE [BOOLEAN], INTEGER_16]
1339 -- function43: FUNCTION [ANY, TUPLE [BOOLEAN], INTEGER_64]
1340 -- function44: FUNCTION [ANY, TUPLE [BOOLEAN], NATURAL]
1341 -- function45: FUNCTION [ANY, TUPLE [BOOLEAN], NATURAL_8]
1342 -- function46: FUNCTION [ANY, TUPLE [BOOLEAN], NATURAL_16]
1343 -- function47: FUNCTION [ANY, TUPLE [BOOLEAN], NATURAL_64]
1344 -- function48: FUNCTION [ANY, TUPLE [BOOLEAN], REAL_32]
1345 -- function49: FUNCTION [ANY, TUPLE [BOOLEAN], REAL_64]
1346 -- function50: FUNCTION [ANY, TUPLE [BOOLEAN], BOOLEAN]
1347 -- function51: FUNCTION [ANY, TUPLE [BOOLEAN], CHARACTER]
1348 -- function52: FUNCTION [ANY, TUPLE [BOOLEAN], CHARACTER_32]
1349 -- function53: FUNCTION [ANY, TUPLE [BOOLEAN], POINTER]
1350 -- function54: FUNCTION [ANY, TUPLE [BOOLEAN], ANY]
1351
1352
1353
1354 -- function40: FUNCTION [ANY, TUPLE [], INTEGER]
1355 -- function41: FUNCTION [ANY, TUPLE [], INTEGER_8]
1356 -- function42: FUNCTION [ANY, TUPLE [], INTEGER_16]
1357 -- function43: FUNCTION [ANY, TUPLE [], INTEGER_64]
1358 -- function44: FUNCTION [ANY, TUPLE [], NATURAL]
1359 -- function45: FUNCTION [ANY, TUPLE [], NATURAL_8]
1360 -- function46: FUNCTION [ANY, TUPLE [], NATURAL_16]
1361 -- function47: FUNCTION [ANY, TUPLE [], NATURAL_64]
1362 -- function48: FUNCTION [ANY, TUPLE [], REAL_32]
1363 -- function49: FUNCTION [ANY, TUPLE [], REAL_64]
1364 -- function50: FUNCTION [ANY, TUPLE [], BOOLEAN]
1365 -- function51: FUNCTION [ANY, TUPLE [], CHARACTER]
1366 -- function52: FUNCTION [ANY, TUPLE [], CHARACTER_32]
1367 -- function53: FUNCTION [ANY, TUPLE [], POINTER]
1368 -- function54: FUNCTION [ANY, TUPLE [], ANY]
1369
1370 -- Those types are here to make sure the byte-code generated on-the-fly
1371 -- works.
1372
1373 feature -- Precondition satisfaction
1374
1375 argument_arrays: ARRAY [ARRAY [INTEGER]]
1376 -- Array for arguments used in predicate evaluation
1377
1378 arguement_tuple_from_indexes (a_indexes: ARRAY [INTEGER]; a_lower: INTEGER; a_upper: INTEGER): TUPLE is
1379 -- Tuple containing objects with `a_indexes'
1380 require
1381 a_indexes_attached: a_indexes /= Void
1382 local
1383 l_count: INTEGER
1384 l_args: like argument_tuple_cache
1385 i: INTEGER
1386 l_arg_tuple: TUPLE
1387 do
1388 -- Load arguments from object pool.
1389 l_count := a_upper - a_lower + 1
1390 l_args := argument_tuple_cache
1391 l_args.wipe_out
1392 from
1393 i := a_lower
1394 until
1395 i > a_upper
1396 loop
1397 l_args.extend (variable_at_index (a_indexes.item (i)))
1398 i := i + 1
1399 end
1400
1401 -- Generate tuple for agent call.
1402 inspect
1403 l_count
1404 when 0 then
1405 l_arg_tuple := []
1406 when 1 then
1407 l_arg_tuple := [l_args.i_th (1)]
1408 when 2 then
1409 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2)]
1410 when 3 then
1411 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3)]
1412 when 4 then
1413 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3), l_args.i_th (4)]
1414 when 5 then
1415 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3), l_args.i_th (4), l_args.i_th (5)]
1416 when 6 then
1417 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3), l_args.i_th (4), l_args.i_th (5), l_args.i_th (6)]
1418 when 7 then
1419 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3), l_args.i_th (4), l_args.i_th (5), l_args.i_th (6), l_args.i_th (7)]
1420 when 8 then
1421 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3), l_args.i_th (4), l_args.i_th (5), l_args.i_th (6), l_args.i_th (7), l_args.i_th (8)]
1422 when 9 then
1423 l_arg_tuple := [l_args.i_th (1), l_args.i_th (2), l_args.i_th (3), l_args.i_th (4), l_args.i_th (5), l_args.i_th (6), l_args.i_th (7), l_args.i_th (8), l_args.i_th (9)]
1424 end
1425 Result := l_arg_tuple
1426 ensure
1427 result_attached: Result /= Void Result.count = a_indexes.count
1428 end
1429
1430
1431 feature -- Predicate evaluation
1432
1433 predicate_table: HASH_TABLE [FUNCTION [ANY, TUPLE, BOOLEAN], INTEGER]
1434 -- Table for predicates that are to be monitered during testing
1435 -- [Agent for the predicate, predicate index]
1436 -- predicate index is 1-based, it is the identifier associated with
1437 -- every unique predicate. See {AUT_PREDICATE}.`id' for more information.
1438
1439 predicate_arity: HASH_TABLE [INTEGER, INTEGER]
1440 -- Arity of predicates in `preciate_table'.
1441 -- [Predicate arity, predicate index].
1442 -- predicate index is 1-based, it is the identifier associated with
1443 -- every unique predicate. See {AUT_PREDICATE}.`id' for more information.
1444
1445 initialize_predicates
1446 -- Initialize `predicate_table' and `predicate_arity'.
1447 do
1448 end
1449
1450 evaluated_predicate_result (a_predicate_id: INTEGER; a_arguments: ARRAY [INTEGER]; a_lower: INTEGER; a_upper: INTEGER): NATURAL_8 is
1451 -- Evaluated result of predicate with id `a_predicate_id' on objects with index `a_arguments'.
1452 -- `a_lower' and `a_upper' indicates that only the part between [`a_lower', `a_upper'] of `a_arguments' is to be used
1453 -- as arguments during predicate evaluation.
1454 -- The result can be of one of the following values:
1455 -- 0 There was an exception during the evaluation.
1456 -- 1 The evaluation succeeded
1457 -- 2 The evaluation failed
1458 local
1459 l_args: TUPLE
1460 l_predicate: FUNCTION [ANY, TUPLE, BOOLEAN]
1461 do
1462 l_args := arguement_tuple_from_indexes (a_arguments, a_lower, a_upper)
1463 l_predicate := predicate_table.item (a_predicate_id)
1464 Result := safe_predicate_evaluation_result (l_predicate, l_args)
1465 ensure
1466 result_valid: Result = 0 or Result = 1 or Result = 2
1467 end
1468
1469 safe_predicate_evaluation_result (a_predicate: FUNCTION [ANY, TUPLE, BOOLEAN]; a_arguments: TUPLE): NATURAL_8 is
1470 -- Evaluated result of `a_predicate' on `a_arguments'.
1471 -- The result can be of one of the following values:
1472 -- 0 There was an exception during the evaluation.
1473 -- 1 The evaluation succeeded
1474 -- 2 The evaluation failed
1475 require
1476 a_predicate_attached: a_predicate /= Void
1477 a_arguments_attached: a_arguments /= Void
1478 local
1479 l_retried: BOOLEAN
1480 l_result: BOOLEAN
1481 do
1482 if not l_retried then
1483 l_result := a_predicate.item (a_arguments)
1484 if l_result then
1485 Result := 1
1486 else
1487 Result := 2
1488 end
1489 else
1490 Result := 0
1491 end
1492 rescue
1493 l_retried := True
1494 retry
1495 end
1496
1497 report_predicate_evaluate_request is
1498 -- Report a predicate evaluation request.
1499 local
1500 l_checking: BOOLEAN
1501 l_pred_id: INTEGER
1502 l_objects: SPECIAL [INTEGER]
1503 l_arity: INTEGER
1504 l_pred_table: like predicate_table
1505 l_arity_table: like predicate_arity
1506 l_argument_holder: like argument_arrays
1507 i, j: INTEGER
1508 l_count: INTEGER
1509 l_args: ARRAY [INTEGER]
1510 l_arg_index: INTEGER
1511 l_response: LINKED_LIST [TUPLE [INTEGER, SPECIAL [NATURAL_8]]]
1512 l_pred_response: SPECIAL [NATURAL_8]
1513 do
1514 output_buffer.wipe_out
1515 error_buffer.wipe_out
1516 create l_response.make
1517 if attached {LINKED_LIST [TUPLE [predicate_id: INTEGER; objects: SPECIAL [INTEGER]]]} last_request as l_request then
1518 l_checking := {ISE_RUNTIME}.check_assert (False)
1519 l_pred_table := predicate_table
1520 l_arity_table := predicate_arity
1521 l_argument_holder := argument_arrays
1522 from
1523 l_request.start
1524 until
1525 l_request.after
1526 loop
1527 l_pred_id := l_request.item_for_iteration.predicate_id
1528 l_objects := l_request.item_for_iteration.objects
1529 l_arity := l_arity_table.item (l_pred_id)
1530 l_count := l_objects.count
1531
1532 l_args := l_argument_holder.item (l_arity)
1533 if l_arity = 0 then
1534 create l_pred_response.make_filled (0, 1)
1535 else
1536 create l_pred_response.make_empty (l_count // l_arity)
1537
1538 end
1539 j := 0
1540 if l_arity = 0 then
1541 l_pred_response.put (evaluated_predicate_result (l_pred_id, l_args, l_args.lower, l_args.upper), j)
1542 else
1543 from
1544 i := 0
1545 l_arg_index := 1
1546 until
1547 i = l_count
1548 loop
1549 l_args.put (l_objects.item (i), l_arg_index)
1550 if l_arg_index = l_arity then
1551 l_pred_response.put (evaluated_predicate_result (l_pred_id, l_args, l_args.lower, l_args.upper), j)
1552 l_arg_index := 1
1553 j := j + 1
1554 else
1555 l_arg_index := l_arg_index + 1
1556 end
1557 i := i + 1
1558 end
1559 end
1560 l_response.extend ([l_pred_id, l_pred_response])
1561 l_request.forth
1562 end
1563 l_checking := {ISE_RUNTIME}.check_assert (l_checking)
1564 last_response := [l_response, output_buffer, error_buffer]
1565 refresh_last_response_flag
1566 send_response_to_socket
1567 else
1568 report_error (invalid_predicate_evaluation_request)
1569 report_error (last_request.generating_type)
1570 refresh_last_response_flag
1571 send_response_to_socket
1572 end
1573 end
1574
1575 relevant_predicate_table: HASH_TABLE [ARRAY [TUPLE [predicate_id: INTEGER; operand_index: SPECIAL [INTEGER]]], INTEGER]
1576 -- Table of relevant predicates for feature
1577 -- Key is the feature id, value is a list of predicates with its predicate id and operand index for that feature.
1578 -- The array as items of the table are 1-based.
1579
1580 is_predicate_evaluation_enabled: BOOLEAN
1581 -- Should predicates in `relevant_predicate_table' be evaluated
1582 -- after execution of a feature?
1583
1584 evaluated_predicate_results (a_feature_id: INTEGER; a_operands: SPECIAL [INTEGER]): ARRAY [NATURAL_8] is
1585 -- Evaluate relevant predicates from `relevant_predicat_table' for
1586 -- feature with `a_feature_id' on operands `a_operands'.
1587 -- Result is a list of responses for each predicate in `l_predicates', the order of the result
1588 -- corresponds to the predicate order in `l_predicates'.
1589 -- 0 means don't know (may because an exception occurred during evaluation)
1590 -- 1 means the predicate evaluated to True,
1591 -- 2 means the predicate evaluated to False.
1592 require
1593 a_feature_id_positive: a_feature_id > 0
1594 a_feature_id_exists: relevant_predicate_table.has (a_feature_id)
1595 a_operands_attached: a_operands /= Void
1596 local
1597 i, j: INTEGER
1598 l_arg_count: INTEGER
1599 l_upper: INTEGER
1600 l_count: INTEGER
1601 l_predicate_result: NATURAL_8
1602 l_predicates: ARRAY [TUPLE [predicate_id: INTEGER; operand_index: SPECIAL [INTEGER]]]
1603 l_pred_data: TUPLE [predicate_id: INTEGER; operand_index: SPECIAL [INTEGER]]
1604 l_arguments: like argument_cache
1605 l_arg_positions: SPECIAL [INTEGER]
1606 l_checking: BOOLEAN
1607 do
1608 l_predicates := relevant_predicate_table.item (a_feature_id)
1609 create Result.make (1, l_predicates.count)
1610 l_arguments := argument_cache
1611 l_checking := {ISE_RUNTIME}.check_assert (False)
1612 from
1613 i := 1
1614 l_count := l_predicates.upper
1615 until
1616 i > l_count
1617 loop
1618 l_pred_data := l_predicates.item (i)
1619 l_arg_positions := l_pred_data.operand_index
1620 l_upper := l_arg_positions.count
1621 from
1622 j := 0
1623 l_arg_count := l_arg_positions.count
1624 until
1625 j = l_arg_count
1626 loop
1627 l_arguments.put (a_operands.item (l_arg_positions.item (j)), j + 1)
1628 j := j + 1
1629 end
1630
1631 l_predicate_result := evaluated_predicate_result (l_pred_data.predicate_id, l_arguments, 1, l_upper)
1632 Result.put (l_predicate_result, i)
1633 i := i + 1
1634 end
1635 l_checking := {ISE_RUNTIME}.check_assert (l_checking)
1636 ensure
1637 result_attached: Result /= Void
1638 result_valid: Result.lower = 1 and then Result.count = relevant_predicate_table.item (a_feature_id).count
1639 end
1640
1641 argument_cache: ARRAY [INTEGER]
1642 -- Cache for arguments used in predicate evaluation
1643
1644 argument_tuple_cache: ARRAYED_LIST [detachable ANY]
1645 -- Cache for arguments used in predicate evaluation.
1646
1647 value_of_object (a_object: ANY; a_type: STRING): STRING is
1648 -- Value of `a_object', which is of type `a_type'
1649 require
1650 a_type_attached: a_type /= Void
1651 do
1652 if primitive_types.has (a_type) then
1653 Result := a_object.out
1654 else
1655 Result := "__REF__"
1656 end
1657 ensure
1658 result_attached: Result /= Void
1659 not_result_is_empty: not Result.is_empty
1660 end
1661
1662 primitive_types: HASH_TABLE [INTEGER, STRING]
1663 -- Names for primitive types
1664
1665 feature -- Test case serialization
1666
1667 test_case_serialization_file: detachable RAW_FILE
1668 -- File to store serialized test cases.
1669
1670 test_state_file: PLAIN_TEXT_FILE
1671 -- File to store test case states
1672
1673 test_case_serializer: ITP_TEST_CASE_SERIALIZER
1674 -- Test case serializer
1675
1676 retrieve_test_case_prestate (a_data: detachable ANY)
1677 -- Retrieve prestate of operands for the test case to be executed next.
1678 -- Store serialized objects in `serialized_objects' and
1679 -- object state information on `objects_summary'.
1680 local
1681 l_serializer: like test_case_serializer
1682 do
1683 l_serializer := test_case_serializer
1684 l_serializer.set_is_test_case_valid (False)
1685
1686 if attached {detachable ARRAY [detachable ANY]} a_data as l_extra_data then
1687 l_serializer.setup_test_case (l_extra_data.item (extra_data_index_test_case_serialization))
1688
1689 if l_serializer.is_test_case_setup then
1690 l_serializer.retrieve_pre_state
1691 end
1692 end
1693 end
1694
1695 retrieve_post_test_case_state
1696 -- Retrieve post test case state.
1697 do
1698 if test_case_serializer.is_test_case_setup then
1699 test_case_serializer.retrieve_post_state (is_failing_test_case)
1700 end
1701 end
1702
1703 log_test_case_serialization
1704 -- Log serialization of the last test case into log file.
1705 local
1706 l_data: TUPLE [serialization:STRING; states: STRING]
1707 do
1708 last_test_case_serialization := Void
1709 if test_case_serializer.is_test_case_setup and then not is_invalid_test_case and then not is_last_invariant_violated then
1710 if
1711 (is_passing_test_case_serialized and (not is_failing_test_case)) or
1712 (is_failing_test_case_serialized and is_failing_test_case)
1713 then
1714 l_data := test_case_serializer.string_representation
1715 if not l_data.serialization.is_empty then
1716 test_case_serialization_file.put_string (l_data.serialization)
1717 end
1718 if not l_data.states.is_empty then
1719 test_state_file.put_string (l_data.states)
1720 end
1721 if is_last_test_case_serialization_passed_to_proxy then
1722 last_test_case_serialization := [l_data.serialization]
1723 end
1724 end
1725 end
1726 end
1727
1728 is_test_case_serialization_enabled: BOOLEAN
1729 -- Is test case serialization enabled?
1730
1731 is_duplicated_test_case_serialized: BOOLEAN
1732 -- Should duplicated test case be serialized?
1733
1734 agent_creation_info: HASH_TABLE [ITP_AGENT_CREATION_INFO, INTEGER]
1735 -- Information about already created agent objects.
1736 -- Key is variable ID, value is the agent creation information describing
1737 -- how that agent is created.
1738
1739 is_test_case_agent_creation: BOOLEAN
1740 -- Is the test case to-be-executed an agent creation?
1741
1742 last_test_case_serialization: TUPLE [serialization: STRING]
1743 -- Serialization data for the last executed test case
1744 -- Void if serialization is disabled or no serialization is retrieved.
1745
1746 is_last_test_case_serialization_passed_to_proxy: BOOLEAN
1747 -- Should `last_test_case_serialization' be passed back to the proxy side
1748 -- during testing? Used for online analysis, for example, precondition-reduction.
1749
1750 feature -- Semantic search
1751
1752 is_batch_assignment: BOOLEAN
1753 -- Is last request a batch-assignment?
1754
1755 special_type_mapping: HASH_TABLE [INTEGER, INTEGER]
1756 -- Mapping betwwen dynamic type of SPECIAL instances
1757 -- to abstract element types.
1758 local
1759 l_int: INTERNAL
1760 once
1761 create l_int
1762 create Result.make (10)
1763 Result.put ({INTERNAL}.boolean_type, ({BOOLEAN}).type_id)
1764 Result.put ({INTERNAL}.character_8_type, ({CHARACTER_8}).type_id)
1765 Result.put ({INTERNAL}.character_32_type, ({CHARACTER_32}).type_id)
1766
1767 Result.put ({INTERNAL}.natural_8_type, ({NATURAL_8}).type_id)
1768 Result.put ({INTERNAL}.natural_16_type, ({NATURAL_16}).type_id)
1769 Result.put ({INTERNAL}.natural_32_type, ({NATURAL_32}).type_id)
1770 Result.put ({INTERNAL}.natural_64_type, ({NATURAL_64}).type_id)
1771
1772 Result.put ({INTERNAL}.integer_8_type, ({INTEGER_8}).type_id)
1773 Result.put ({INTERNAL}.integer_16_type, ({INTEGER_16}).type_id)
1774 Result.put ({INTERNAL}.integer_32_type, ({INTEGER_32}).type_id)
1775 Result.put ({INTERNAL}.integer_64_type, ({INTEGER_64}).type_id)
1776
1777 Result.put ({INTERNAL}.real_32_type, ({REAL_32}).type_id)
1778 Result.put ({INTERNAL}.real_64_type, ({REAL_64}).type_id)
1779
1780 Result.put ({INTERNAL}.pointer_type, ({POINTER}).type_id)
1781 ensure
1782 special_type_mapping_not_void: Result /= Void
1783 end
1784
1785 invariant
1786 log_file_open_write: log_file.is_open_write
1787 store_not_void: store /= Void
1788 output_buffer_attached: output_buffer /= Void
1789 error_buffer_attached: error_buffer /= Void
1790 socket_attached: socket /= Void
1791
1792 note
1793 copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
1794 license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
1795 source: "[
1796 Eiffel Software
1797 5949 Hollister Ave., Goleta, CA 93117 USA
1798 Telephone 805-685-1006, Fax 805-685-6869
1799 Website http://www.eiffel.com
1800 Customer support http://support.eiffel.com
1801 ]"
1802 end
1803

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23