The first: if you use GNAT compiler, you have to add flag -gnata to compiler flags or use configuration file for GNAT with pragma Assertion_Policy(Check); to enable check for Pre- and Post-conditions. Without one of these options, all checks are ignored. This is why you are allowed to violate them.
Preconditions take place right before the selected subprogram is executed. For example, the function declared as:
function Add(A, B: Positive) return Positive is (A + B) with
Pre => A < 10;
This precondition will be checked before the function will be executed. For example:
I := Add(2, 2);
Put_Line(Positive'Image(I)); -- prints 4 as expected
begin
I := Add(10, 2); -- Crash, exception on violation of precondition
exception
when ASSERT_FAILURE =>
Put_Line(Positive'Image(I)); -- prints 4
end;
Postconditions are checked on subprograms after their execution. Another example:
procedure Increment(A: in out Positive) with
Post => A < 20 is
begin
A := A + 1;
end Increment;
And usage:
I := 2;
Increment(I);
Put_Line(Positive'Image(I)); -- prints 3
I := 19;
begin
I := Increment(I); -- Crash, exception on violation of postcondition
exception
when ASSERT_FAILURE =>
Put_Line(Positive'Image(I)); -- prints 19
end;