3 with Ada
.Text_IO
; use Ada
.Text_IO
;
5 with GNAT
.Lists
; use GNAT
.Lists
;
7 procedure Linkedlist
is
8 procedure Destroy
(Val
: in out Integer) is null;
10 package Integer_Lists
is new Doubly_Linked_Lists
11 (Element_Type
=> Integer,
13 Destroy_Element
=> Destroy
);
18 L
: Doubly_Linked_List
;
21 -- Ensure that none of the elements in the range Low_Elem .. High_Elem are
22 -- present in list L, and that the list's length is 0.
24 procedure Check_Locked_Mutations
26 L
: in out Doubly_Linked_List
);
27 -- Ensure that all mutation operations of list L are locked
29 procedure Check_Present
31 L
: Doubly_Linked_List
;
34 -- Ensure that all elements in the range Low_Elem .. High_Elem are present
37 procedure Check_Unlocked_Mutations
39 L
: in out Doubly_Linked_List
);
40 -- Ensure that all mutation operations of list L are unlocked
42 procedure Populate_With_Append
43 (L
: Doubly_Linked_List
;
46 -- Add elements in the range Low_Elem .. High_Elem in that order in list L
48 procedure Test_Append
;
49 -- Verify that Append properly inserts at the tail of a list
51 procedure Test_Contains
54 -- Verify that Contains properly identifies that elements in the range
55 -- Low_Elem .. High_Elem are within a list.
57 procedure Test_Create
;
58 -- Verify that all list operations fail on a non-created list
63 -- Verify that Delete properly removes elements in the range Low_Elem ..
64 -- High_Elem from a list.
66 procedure Test_Delete_First
69 -- Verify that Delete properly removes elements in the range Low_Elem ..
70 -- High_Elem from the head of a list.
72 procedure Test_Delete_Last
75 -- Verify that Delete properly removes elements in the range Low_Elem ..
76 -- High_Elem from the tail of a list.
79 -- Verify that First properly returns the head of a list
81 procedure Test_Insert_After
;
82 -- Verify that Insert_After properly adds an element after some other
85 procedure Test_Insert_Before
;
86 -- Vefity that Insert_Before properly adds an element before some other
89 procedure Test_Is_Empty
;
90 -- Verify that Is_Empty properly returns this status of a list
92 procedure Test_Iterate
;
93 -- Verify that iterators properly manipulate mutation operations
95 procedure Test_Iterate_Empty
;
96 -- Verify that iterators properly manipulate mutation operations of an
99 procedure Test_Iterate_Forced
101 High_Elem
: Integer);
102 -- Verify that an iterator that is forcefully advanced by Next properly
103 -- unlocks the mutation operations of a list.
106 -- Verify that Last properly returns the tail of a list
108 procedure Test_Prepend
;
109 -- Verify that Prepend properly inserts at the head of a list
111 procedure Test_Replace
;
112 -- Verify that Replace properly substitutes old elements with new ones
115 -- Verify that Size returns the correct size of a list
121 procedure Check_Empty
123 L
: Doubly_Linked_List
;
127 Len
: constant Natural := Size
(L
);
130 for Elem
in Low_Elem
.. High_Elem
loop
131 if Contains
(L
, Elem
) then
132 Put_Line
("ERROR: " & Caller
& ": extra element" & Elem
'Img);
137 Put_Line
("ERROR: " & Caller
& ": wrong length");
138 Put_Line
("expected: 0");
139 Put_Line
("got :" & Len
'Img);
143 ----------------------------
144 -- Check_Locked_Mutations --
145 ----------------------------
147 procedure Check_Locked_Mutations
149 L
: in out Doubly_Linked_List
) is
153 Put_Line
("ERROR: " & Caller
& ": Append: no exception raised");
158 Put_Line
("ERROR: " & Caller
& ": Append: unexpected exception");
163 Put_Line
("ERROR: " & Caller
& ": Delete: no exception raised");
170 Put_Line
("ERROR: " & Caller
& ": Delete: unexpected exception");
175 Put_Line
("ERROR: " & Caller
& ": Delete_First: no exception raised");
183 ("ERROR: " & Caller
& ": Delete_First: unexpected exception");
188 Put_Line
("ERROR: " & Caller
& ": Delete_List: no exception raised");
196 ("ERROR: " & Caller
& ": Delete_Last: unexpected exception");
201 Put_Line
("ERROR: " & Caller
& ": Destroy: no exception raised");
206 Put_Line
("ERROR: " & Caller
& ": Destroy: unexpected exception");
210 Insert_After
(L
, 1, 2);
211 Put_Line
("ERROR: " & Caller
& ": Insert_After: no exception raised");
217 ("ERROR: " & Caller
& ": Insert_After: unexpected exception");
221 Insert_Before
(L
, 1, 2);
223 ("ERROR: " & Caller
& ": Insert_Before: no exception raised");
229 ("ERROR: " & Caller
& ": Insert_Before: unexpected exception");
234 Put_Line
("ERROR: " & Caller
& ": Prepend: no exception raised");
239 Put_Line
("ERROR: " & Caller
& ": Prepend: unexpected exception");
244 Put_Line
("ERROR: " & Caller
& ": Replace: no exception raised");
249 Put_Line
("ERROR: " & Caller
& ": Replace: unexpected exception");
251 end Check_Locked_Mutations
;
257 procedure Check_Present
259 L
: Doubly_Linked_List
;
268 for Exp_Elem
in Low_Elem
.. High_Elem
loop
271 if Elem
/= Exp_Elem
then
272 Put_Line
("ERROR: " & Caller
& ": Check_Present: wrong element");
273 Put_Line
("expected:" & Exp_Elem
'Img);
274 Put_Line
("got :" & Elem
'Img);
278 -- At this point all elements should have been accounted for. Check for
281 while Has_Next
(Iter
) loop
284 ("ERROR: " & Caller
& ": Check_Present: extra element" & Elem
'Img);
288 when Iterator_Exhausted
=>
292 & "Check_Present: incorrect number of elements");
295 ------------------------------
296 -- Check_Unlocked_Mutations --
297 ------------------------------
299 procedure Check_Unlocked_Mutations
301 L
: in out Doubly_Linked_List
)
310 Insert_After
(L
, 2, 3);
311 Insert_Before
(L
, 2, 1);
314 end Check_Unlocked_Mutations
;
316 --------------------------
317 -- Populate_With_Append --
318 --------------------------
320 procedure Populate_With_Append
321 (L
: Doubly_Linked_List
;
326 for Elem
in Low_Elem
.. High_Elem
loop
329 end Populate_With_Append
;
335 procedure Test_Append
is
336 L
: Doubly_Linked_List
:= Create
;
346 (Caller
=> "Test_Append",
358 procedure Test_Contains
362 Low_Bogus
: constant Integer := Low_Elem
- 1;
363 High_Bogus
: constant Integer := High_Elem
+ 1;
365 L
: Doubly_Linked_List
:= Create
;
368 Populate_With_Append
(L
, Low_Elem
, High_Elem
);
370 -- Ensure that the elements are contained in the list
372 for Elem
in Low_Elem
.. High_Elem
loop
373 if not Contains
(L
, Elem
) then
375 ("ERROR: Test_Contains: element" & Elem
'Img & " not in list");
379 -- Ensure that arbitrary elements which were not inserted in the list
380 -- are not contained in the list.
382 if Contains
(L
, Low_Bogus
) then
384 ("ERROR: Test_Contains: element" & Low_Bogus
'Img & " in list");
387 if Contains
(L
, High_Bogus
) then
389 ("ERROR: Test_Contains: element" & High_Bogus
'Img & " in list");
399 procedure Test_Create
is
403 L
: Doubly_Linked_List
;
407 -- Ensure that every routine defined in the API fails on a list which
408 -- has not been created yet.
412 Put_Line
("ERROR: Test_Create: Append: no exception raised");
417 Put_Line
("ERROR: Test_Create: Append: unexpected exception");
421 Flag
:= Contains
(L
, 1);
422 Put_Line
("ERROR: Test_Create: Contains: no exception raised");
427 Put_Line
("ERROR: Test_Create: Contains: unexpected exception");
432 Put_Line
("ERROR: Test_Create: Delete: no exception raised");
437 Put_Line
("ERROR: Test_Create: Delete: unexpected exception");
442 Put_Line
("ERROR: Test_Create: Delete_First: no exception raised");
448 ("ERROR: Test_Create: Delete_First: unexpected exception");
453 Put_Line
("ERROR: Test_Create: Delete_Last: no exception raised");
458 Put_Line
("ERROR: Test_Create: Delete_Last: unexpected exception");
463 Put_Line
("ERROR: Test_Create: First: no exception raised");
468 Put_Line
("ERROR: Test_Create: First: unexpected exception");
472 Insert_After
(L
, 1, 2);
473 Put_Line
("ERROR: Test_Create: Insert_After: no exception raised");
479 ("ERROR: Test_Create: Insert_After: unexpected exception");
483 Insert_Before
(L
, 1, 2);
484 Put_Line
("ERROR: Test_Create: Insert_Before: no exception raised");
490 ("ERROR: Test_Create: Insert_Before: unexpected exception");
494 Flag
:= Is_Empty
(L
);
495 Put_Line
("ERROR: Test_Create: Is_Empty: no exception raised");
500 Put_Line
("ERROR: Test_Create: Is_Empty: unexpected exception");
505 Put_Line
("ERROR: Test_Create: Iterate: no exception raised");
510 Put_Line
("ERROR: Test_Create: Iterate: unexpected exception");
515 Put_Line
("ERROR: Test_Create: Last: no exception raised");
520 Put_Line
("ERROR: Test_Create: Last: unexpected exception");
525 Put_Line
("ERROR: Test_Create: Prepend: no exception raised");
530 Put_Line
("ERROR: Test_Create: Prepend: unexpected exception");
535 Put_Line
("ERROR: Test_Create: Replace: no exception raised");
540 Put_Line
("ERROR: Test_Create: Replace: unexpected exception");
545 Put_Line
("ERROR: Test_Create: Size: no exception raised");
550 Put_Line
("ERROR: Test_Create: Size: unexpected exception");
558 procedure Test_Delete
563 L
: Doubly_Linked_List
:= Create
;
566 Populate_With_Append
(L
, Low_Elem
, High_Elem
);
568 -- Delete the first element, which is technically the head
570 Delete
(L
, Low_Elem
);
572 -- Ensure that all remaining elements except for the head are present in
576 (Caller
=> "Test_Delete",
578 Low_Elem
=> Low_Elem
+ 1,
579 High_Elem
=> High_Elem
);
581 -- Delete the last element, which is technically the tail
583 Delete
(L
, High_Elem
);
585 -- Ensure that all remaining elements except for the head and tail are
586 -- present in the list.
589 (Caller
=> "Test_Delete",
591 Low_Elem
=> Low_Elem
+ 1,
592 High_Elem
=> High_Elem
- 1);
594 -- Delete all even elements
596 for Elem
in Low_Elem
+ 1 .. High_Elem
- 1 loop
597 if Elem
mod 2 = 0 then
602 -- Ensure that all remaining elements except the head, tail, and even
603 -- elements are present in the list.
605 for Elem
in Low_Elem
+ 1 .. High_Elem
- 1 loop
606 if Elem
mod 2 /= 0 and then not Contains
(L
, Elem
) then
607 Put_Line
("ERROR: Test_Delete: missing element" & Elem
'Img);
611 -- Delete all odd elements
613 for Elem
in Low_Elem
+ 1 .. High_Elem
- 1 loop
614 if Elem
mod 2 /= 0 then
619 -- At this point the list should be completely empty
622 (Caller
=> "Test_Delete",
624 Low_Elem
=> Low_Elem
,
625 High_Elem
=> High_Elem
);
627 -- Try to delete an element. This operation should raise List_Empty.
630 Delete
(L
, Low_Elem
);
631 Put_Line
("ERROR: Test_Delete: List_Empty not raised");
636 Put_Line
("ERROR: Test_Delete: unexpected exception");
642 -----------------------
643 -- Test_Delete_First --
644 -----------------------
646 procedure Test_Delete_First
650 L
: Doubly_Linked_List
:= Create
;
653 Populate_With_Append
(L
, Low_Elem
, High_Elem
);
655 -- Delete the head of the list, and verify that the remaining elements
656 -- are still present in the list.
658 for Elem
in Low_Elem
.. High_Elem
loop
662 (Caller
=> "Test_Delete_First",
664 Low_Elem
=> Elem
+ 1,
665 High_Elem
=> High_Elem
);
668 -- At this point the list should be completely empty
671 (Caller
=> "Test_Delete_First",
673 Low_Elem
=> Low_Elem
,
674 High_Elem
=> High_Elem
);
676 -- Try to delete an element. This operation should raise List_Empty.
680 Put_Line
("ERROR: Test_Delete_First: List_Empty not raised");
685 Put_Line
("ERROR: Test_Delete_First: unexpected exception");
689 end Test_Delete_First
;
691 ----------------------
692 -- Test_Delete_Last --
693 ----------------------
695 procedure Test_Delete_Last
699 L
: Doubly_Linked_List
:= Create
;
702 Populate_With_Append
(L
, Low_Elem
, High_Elem
);
704 -- Delete the tail of the list, and verify that the remaining elements
705 -- are still present in the list.
707 for Elem
in reverse Low_Elem
.. High_Elem
loop
711 (Caller
=> "Test_Delete_Last",
713 Low_Elem
=> Low_Elem
,
714 High_Elem
=> Elem
- 1);
717 -- At this point the list should be completely empty
720 (Caller
=> "Test_Delete_Last",
722 Low_Elem
=> Low_Elem
,
723 High_Elem
=> High_Elem
);
725 -- Try to delete an element. This operation should raise List_Empty.
729 Put_Line
("ERROR: Test_Delete_Last: List_Empty not raised");
734 Put_Line
("ERROR: Test_Delete_First: unexpected exception");
738 end Test_Delete_Last
;
744 procedure Test_First
is
746 L
: Doubly_Linked_List
:= Create
;
749 -- Try to obtain the head. This operation should raise List_Empty.
753 Put_Line
("ERROR: Test_First: List_Empty not raised");
758 Put_Line
("ERROR: Test_First: unexpected exception");
761 Populate_With_Append
(L
, 1, 2);
768 Put_Line
("ERROR: Test_First: wrong element");
769 Put_Line
("expected: 1");
770 Put_Line
("got :" & Elem
'Img);
776 -----------------------
777 -- Test_Insert_After --
778 -----------------------
780 procedure Test_Insert_After
is
781 L
: Doubly_Linked_List
:= Create
;
784 -- Try to insert after a non-inserted element, in an empty list
786 Insert_After
(L
, 1, 2);
788 -- At this point the list should be completely empty
791 (Caller
=> "Test_Insert_After",
798 Insert_After
(L
, 1, 3); -- 1, 3
799 Insert_After
(L
, 1, 2); -- 1, 2, 3
800 Insert_After
(L
, 3, 4); -- 1, 2, 3, 4
802 -- Try to insert after a non-inserted element, in a full list
804 Insert_After
(L
, 10, 11);
807 (Caller
=> "Test_Insert_After",
813 end Test_Insert_After
;
815 ------------------------
816 -- Test_Insert_Before --
817 ------------------------
819 procedure Test_Insert_Before
is
820 L
: Doubly_Linked_List
:= Create
;
823 -- Try to insert before a non-inserted element, in an empty list
825 Insert_Before
(L
, 1, 2);
827 -- At this point the list should be completely empty
830 (Caller
=> "Test_Insert_Before",
837 Insert_Before
(L
, 4, 2); -- 2, 4
838 Insert_Before
(L
, 2, 1); -- 1, 2, 4
839 Insert_Before
(L
, 4, 3); -- 1, 2, 3, 4
841 -- Try to insert before a non-inserted element, in a full list
843 Insert_Before
(L
, 10, 11);
846 (Caller
=> "Test_Insert_Before",
852 end Test_Insert_Before
;
858 procedure Test_Is_Empty
is
859 L
: Doubly_Linked_List
:= Create
;
862 if not Is_Empty
(L
) then
863 Put_Line
("ERROR: Test_Is_Empty: list is not empty");
869 Put_Line
("ERROR: Test_Is_Empty: list is empty");
874 if not Is_Empty
(L
) then
875 Put_Line
("ERROR: Test_Is_Empty: list is not empty");
885 procedure Test_Iterate
is
889 L
: Doubly_Linked_List
:= Create
;
892 Populate_With_Append
(L
, 1, 5);
894 -- Obtain an iterator. This action must lock all mutation operations of
897 Iter_1
:= Iterate
(L
);
899 -- Ensure that every mutation routine defined in the API fails on a list
900 -- with at least one outstanding iterator.
902 Check_Locked_Mutations
903 (Caller
=> "Test_Iterate",
906 -- Obtain another iterator
908 Iter_2
:= Iterate
(L
);
910 -- Ensure that every mutation is still locked
912 Check_Locked_Mutations
913 (Caller
=> "Test_Iterate",
916 -- Exhaust the first itertor
918 while Has_Next
(Iter_1
) loop
922 -- Ensure that every mutation is still locked
924 Check_Locked_Mutations
925 (Caller
=> "Test_Iterate",
928 -- Exhaust the second itertor
930 while Has_Next
(Iter_2
) loop
934 -- Ensure that all mutation operations are once again callable
936 Check_Unlocked_Mutations
937 (Caller
=> "Test_Iterate",
943 ------------------------
944 -- Test_Iterate_Empty --
945 ------------------------
947 procedure Test_Iterate_Empty
is
950 L
: Doubly_Linked_List
:= Create
;
953 -- Obtain an iterator. This action must lock all mutation operations of
958 -- Ensure that every mutation routine defined in the API fails on a list
959 -- with at least one outstanding iterator.
961 Check_Locked_Mutations
962 (Caller
=> "Test_Iterate_Empty",
965 -- Attempt to iterate over the elements
967 while Has_Next
(Iter
) loop
971 ("ERROR: Test_Iterate_Empty: element" & Elem
'Img & " exists");
974 -- Ensure that all mutation operations are once again callable
976 Check_Unlocked_Mutations
977 (Caller
=> "Test_Iterate_Empty",
981 end Test_Iterate_Empty
;
983 -------------------------
984 -- Test_Iterate_Forced --
985 -------------------------
987 procedure Test_Iterate_Forced
993 L
: Doubly_Linked_List
:= Create
;
996 Populate_With_Append
(L
, Low_Elem
, High_Elem
);
998 -- Obtain an iterator. This action must lock all mutation operations of
1001 Iter
:= Iterate
(L
);
1003 -- Ensure that every mutation routine defined in the API fails on a list
1004 -- with at least one outstanding iterator.
1006 Check_Locked_Mutations
1007 (Caller
=> "Test_Iterate_Forced",
1010 -- Forcibly advance the iterator until it raises an exception
1013 for Guard
in Low_Elem
.. High_Elem
+ 1 loop
1018 ("ERROR: Test_Iterate_Forced: Iterator_Exhausted not raised");
1020 when Iterator_Exhausted
=>
1023 Put_Line
("ERROR: Test_Iterate_Forced: unexpected exception");
1026 -- Ensure that all mutation operations are once again callable
1028 Check_Unlocked_Mutations
1029 (Caller
=> "Test_Iterate_Forced",
1033 end Test_Iterate_Forced
;
1039 procedure Test_Last
is
1041 L
: Doubly_Linked_List
:= Create
;
1044 -- Try to obtain the tail. This operation should raise List_Empty.
1048 Put_Line
("ERROR: Test_Last: List_Empty not raised");
1053 Put_Line
("ERROR: Test_Last: unexpected exception");
1056 Populate_With_Append
(L
, 1, 2);
1063 Put_Line
("ERROR: Test_Last: wrong element");
1064 Put_Line
("expected: 2");
1065 Put_Line
("got :" & Elem
'Img);
1075 procedure Test_Prepend
is
1076 L
: Doubly_Linked_List
:= Create
;
1086 (Caller
=> "Test_Prepend",
1098 procedure Test_Replace
is
1099 L
: Doubly_Linked_List
:= Create
;
1102 Populate_With_Append
(L
, 1, 5);
1110 Replace
(L
, 11, 12);
1113 (Caller
=> "Test_Replace",
1125 procedure Test_Size
is
1126 L
: Doubly_Linked_List
:= Create
;
1133 Put_Line
("ERROR: Test_Size: wrong size");
1134 Put_Line
("expected: 0");
1135 Put_Line
("got :" & S
'Img);
1138 Populate_With_Append
(L
, 1, 2);
1142 Put_Line
("ERROR: Test_Size: wrong size");
1143 Put_Line
("expected: 2");
1144 Put_Line
("got :" & S
'Img);
1147 Populate_With_Append
(L
, 3, 6);
1151 Put_Line
("ERROR: Test_Size: wrong size");
1152 Put_Line
("expected: 6");
1153 Put_Line
("got :" & S
'Img);
1159 -- Start of processing for Operations