Assertions

From Rosetta Code
Task
Assertions
You are encouraged to solve this task according to the task description, using any language you may know.

Assertions are a way of breaking out of code when there is an error or an unexpected input.

Some languages throw exceptions and some treat it as a break point.


Task

Show an assertion in your language by asserting that an integer variable is equal to 42.

11l

Translation of: Python

<lang 11l>V a = 5 assert(a == 42) assert(a == 42, ‘Error message’)</lang>

68000 Assembly

The TRAP instruction is used for error handling. Execution jumps to a specified memory address stored in the "trap table." Depending on the hardware, the exception handling subroutine is either built into the kernel or is defined by the programmer.

<lang 68000devpac>CMP.L #42,D0 BEQ continue

   ILLEGAL    ;jumps to Trap 4.

continue:

rest of program</lang>

Ada

Using pragma Assert: <lang ada>pragma Assert (A = 42, "Oops!");</lang> The behavior of pragma is controlled by pragma Assertion_Policy. Another way is to use the predefined package Ada.Assertions: <lang ada>with Ada.Assertions; use Ada.Assertions; ... Assert (A = 42, "Oops!");</lang> The procedure Assert propagates Assertion_Error when condition is false. Since Ada 2012 one may also specify preconditions and post-conditions for a subprogram. <lang ada>procedure Find_First

    (List     : in     Array_Type;
     Value    : in     Integer;
     Found    :    out Boolean;
     Position :    out Positive) with
     Depends => ((Found, Position) => (List, Value)),
     Pre     => (List'Length > 0),
     Post    =>
     (if Found then Position in List'Range and then List (Position) = Value
      else Position = List'Last);</lang>

The precondition identified with "Pre =>" is an assertion that the length of the parameter List must be greater than zero. The post-condition identified with "Post =>" asserts that, upon completion of the procedure, if Found is true then Position is a valid index value in List and the value at the array element List(Position) equals the value of the Value parameter. If Found is False then Position is set to the highest valid index value for List.

Aime

<lang aime>integer x;

x = 41; if (x != 42) {

   error("x is not 42");

}</lang> Executing the program will produce on standard error:

aime: assert: 5: x is not 42

ALGOL 68

The "Revised Report on the Algorithmic Language - ALGOL 68" suggest that ASSERT may be made available by a particular implementation, quote: "Pragmats may ... convey to the implementation some piece of information affecting some aspect of the meaning of the program which is not defined by this Report,..."

Example given[1]:

INT a, b; read((a, b)) PR ASSERT a >= 0 & b > 0 PR;

This works with neither ELLA ALGOL 68 nor ALGOL 68G.

The standard alternative would be to implement the assertions as an exception as per the Exceptions sample code.

In ELLA ALGOL 68 the ASSERT is implemented as an operator in the environment prelude: <lang algol68>OP ASSERT = (VECTOR [] CHAR assertion,BOOL valid) VOID: IF NOT valid THEN type line on terminal(assertion);

       terminal error( 661 {invalid assertion } )

FI;</lang> And can be "USEd" as follows: <lang algol68>PROGRAM assertions CONTEXT VOID USE standard,environment BEGIN

 INT a := 43;
 "Oops!" ASSERT ( a = 42 )

END FINISH</lang>

ALGOL W

Assertions were added to the 1972 version of Algol W. If the tested condition is false, the program terminates. In the following, the write does not get executed.

<lang algolw>begin

   integer a;
   a := 43;
   assert a = 42;
   write( "this won't appear" )

end.</lang>

Apex

Asserts that the specified condition is true. If it is not, a fatal error is returned that causes code execution to halt. <lang apex> String myStr = 'test; System.assert(myStr == 'something else', 'Assertion Failed Message'); </lang>

Asserts that the first two arguments are the same. If they are not, a fatal error is returned that causes code execution to halt. <lang apex> Integer i = 5; System.assertEquals(6, i, 'Expected 6, received ' + i); </lang>

Asserts that the first two arguments are different. If they are the same, a fatal error is returned that causes code execution to halt. <lang apex> Integer i = 5; System.assertNotEquals(5, i, 'Expected different value than ' + i); </lang>

You can’t catch an assertion failure using a try/catch block even though it is logged as an exception.

Arturo

<lang rebol>a: 42 ensure [a = 42]</lang>

AutoHotkey

Exceptions

Works with: AutoHotkey_L

<lang AHK>a := 42 Assert(a > 10) Assert(a < 42) ; throws exception

Assert(bool){

   If !bool
       throw Exception("Expression false", -1)

}</lang>

Legacy versions

<lang AutoHotkey>if (a != 42) { OutputDebug, "a != 42" ; sends output to a debugger if connected ListVars ; lists values of local and global variables Pause ; pauses the script, use ExitApp to exit instead }</lang>

AWK

AWK doesn't have a built-in assert statement. It could be simulated using a user-defined assert() function defined as below. The BEGIN section shows some examples of successful and failed "assertions".

<lang awk> BEGIN { meaning = 6 * 7 assert(meaning == 42, "Integer mathematics failed") assert(meaning == 42) meaning = strtonum("42 also known as forty-two") assert(meaning == 42, "Built-in function failed") meaning = "42" assert(meaning == 42, "Dynamic type conversion failed") meaning = 6 * 9 assert(meaning == 42, "Ford Prefect's experiment failed") print "That's all folks" exit }

  1. Errormsg is optional, displayed if assertion fails

function assert(cond, errormsg){ if (!cond) { if (errormsg != "") print errormsg exit 1 } } </lang>

The above example produces the output below, and sets the program's exit code to 1 (the default is 0)

Ford Prefect's experiment failed

Axe

<lang axe>A=42??Returnʳ</lang>

BaCon

<lang qbasic>' Assertions answer = assertion(42) PRINT "The ultimate answer is indeed ", answer

PRINT "Now, expect a failure, unless NDEBUG defined at compile time" answer = assertion(41) PRINT answer END

' Ensure the given number is the ultimate answer FUNCTION assertion(NUMBER i)

   ' BaCon can easily be intimately integrated with C
   USEH
       #include <assert.h>
   END USEH
   ' If the given expression is not true, abort the program
   USEC
       assert(i == 42);
   END USEC
   RETURN i

END FUNCTION</lang>

Output:
prompt$ bacon -q assertion.bac && ./assertion
Converting 'assertion.bac'... done, 24 lines were processed in 0.006 seconds.
Compiling 'assertion.bac'... cc  -c assertion.bac.c
cc -o assertion assertion.bac.o -lbacon -lm 
Done, program 'assertion' ready.
The ultimate answer is indeed 42
Now, expect a failure, unless NDEBUG defined at compile time
assertion: assertion.assertion.h:16: assertion: Assertion `i == 42' failed.
ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.

prompt$ bacon -q -o '-DNDEBUG' assertion.bac && ./assertion
Converting 'assertion.bac'... done, 24 lines were processed in 0.003 seconds.
Compiling 'assertion.bac'... cc  -DNDEBUG -c assertion.bac.c
cc -o assertion assertion.bac.o -lbacon -lm 
Done, program 'assertion' ready.
The ultimate answer is indeed 42
Now, expect a failure, unless NDEBUG defined at compile time
41

BASIC256

Works with: BASIC256 version 2.0.0.11

<lang BASIC256> subroutine assert (condition, message)

if not condition then print "ASSERTION FAIED: ";message: throwerror 1

end subroutine

call assert(1+1=2, "but I don't expect this assertion to fail"): rem Does not throw an error rem call assert(1+1=3, "and rightly so"): rem Throws an error </lang>

BBC BASIC

<lang bbcbasic> PROCassert(a% = 42)

     END
     
     DEF PROCassert(bool%)
     IF NOT bool% THEN ERROR 100, "Assertion failed"
     ENDPROC</lang>

Brat

<lang brat>squish import :assert :assertions

assert_equal 42 42 assert_equal 13 42 #Raises an exception</lang>

C

<lang c>#include <assert.h>

int main(){

  int a;
  /* ...input or change a here */
  assert(a == 42); /* aborts program when a is not 42, unless the NDEBUG macro was defined */
  return 0;

}</lang> To turn off assertions, simply define the NDEBUG macro before where <assert.h> is included.

There is no mechanism to add a custom "message" with your assertion, like in other languages. However, there is a "trick" to do this, by simply logical-AND-ing your condition with a string constant message, like in the following. Since a string constant is guaranteed to be non-NULL (and hence evaluated as True), and since AND-ing with True is an identity operation for a boolean, it will not alter the behavior of the assertion, but it will get captured in the debug message that is printed: <lang c>assert(a == 42 && "Error message");</lang> This trick only works with messages written directly in the source code (i.e. cannot be a variable or be computed), however, since the assertion message is captured by the macro at compile-time.


C# and Visual Basic .NET

.NET provides the Debug.Assert and Trace.Assert methods, which notify TraceListener instances subscribed to the program's trace output if the specified condition is false. Both methods also have overloads that allow a specified string to be added to the default message of the assertion, which consists of "Assertion Failed" and a stack trace for the location of the assertion.

The behavior of a failed assertion is controlled by the listeners in the TraceListeners collection shared by the Debug and Trace classes. By default, the collection contains an instance of the DefaultTraceListener class, which uses functions in the Windows API that notify attached debuggers, if any. Additional behavior depends on the framework version that the application is running in:

  • In .NET Core applications, if no debuggers are attached, failed Debug.Assert assertions for non-UI applications terminate the program and write the assertion message to the console, while failed Trace.Assert assertions do not affect execution. In this respect, a failed Debug assertion behaves similarly to an exception.
  • In .NET Framework applications, for both types of assertions, a special instance of the Abort-Retry-Ignore message box containing the assertion message is displayed (even with a debugger attached). "Abort" terminates the program; "Retry" switches to the location of the assertion in source code if the application is running in a debugger, or, if none are attached, prompts to launch a just-in-time debugger; and "Ignore" continues execution past the assertion.

Calls to methods of the Debug class are only compiled when the DEBUG compiler constant is defined, and so are intended for asserting invariants in internal code that could only be broken because of logic errors. Calls to methods of the Trace class similarly require the TRACE constant, which, however, is defined by default for both debug and release builds in Visual Studio projects—trace assertions can thus be used for various logging purposes in production code.

<lang csharp>using System.Diagnostics; // Debug and Trace are in this namespace.

static class Program {

   static void Main()
   {
       int a = 0;
       Console.WriteLine("Before");
       // Always hit.
       Trace.Assert(a == 42, "Trace assertion failed");
       Console.WriteLine("After Trace.Assert");
       // Only hit in debug builds.        
       Debug.Assert(a == 42, "Debug assertion failed");
       Console.WriteLine("After Debug.Assert");
   }

}</lang>

<lang vbnet>Imports System.Diagnostics ' Note: VB Visual Studio projects have System.Diagnostics imported by default, ' along with several other namespaces.

Module Program

   Sub Main()
       Dim a As Integer = 0
       Console.WriteLine("Before")
       ' Always hit.
       Trace.Assert(a = 42, "Trace assertion failed: The Answer was incorrect")
       Console.WriteLine("After Trace.Assert")
       ' Only hit in debug builds.        
       Debug.Assert(a = 42, "Debug assertion failed: The Answer was incorrect")
       Console.WriteLine("After Debug.Assert")
   End Sub

End Module</lang>

Output (for .NET Core debug builds when outside of a debugger):
Before
After Trace.Assert
Assertion Failed
Debug assertion failed

   at Program.Main() in FILENAME:line 21
Output:

In .NET Core applications, this is the output

  • when a debugger is attached and is used to continue past both assertions when they fail, or
  • in release builds of the program, where the call to Debug.Assert is removed and the Trace.Assert assertion is hit but has no visible effects.

In .NET Framework applications, assertions never show up in the console and so the output is this when a debugger or the "Ignore" option used to continue past the assertions.

Before
After Trace.Assert
After Debug.Assert

Displaying Trace assertions in console:

To "see" the Trace.Assert assertion, additional TraceListener instances must be subscribed by the program. In the .NET Framework, there are several built-in subclasses of TraceListener, including ConsoleTraceListener, which writes trace messages to the console. In .NET Core, these classes are available starting from .NET Core 3.0.

Subscribing an instance involves adding the following line to the beginning of Main() (with a semicolon in C#, of course ;) <lang vbnet>Trace.Listeners.Add(new ConsoleTraceListener())</lang>

C++

Translation of: C

<lang cpp>#include <cassert> // assert.h also works

int main() {

 int a;
 // ... input or change a here
 assert(a == 42); // Aborts program if a is not 42, unless the NDEBUG macro was defined
                   // when including <cassert>, in which case it has no effect

}</lang> Note that assert does not get a std:: prefix because it's a macro.

Clojure

<lang Clojure> (let [i 42]

    (assert (= i 42)))

</lang>

Common Lisp

<lang lisp>(let ((x 42))

 (assert (and (integerp x) (= 42 x)) (x)))</lang>

Component Pascal

Works with BlackBox Component Builder <lang oberon2> MODULE Assertions; VAR x: INTEGER; PROCEDURE DoIt*; BEGIN x := 41; ASSERT(x = 42); END DoIt; END Assertions.

Assertions.DoIt </lang> Output:

TRAP 0

 Assertions.DoIt   [0000001DH] 
 Kernel.Call   [00001A7CH] 
	.adr	INTEGER	1685454913
	.kind	INTEGER	0
	.n	INTEGER	0
	.p	INTEGER	0
	.par	ARRAY 256 OF INTEGER	elements
	.r	REAL	8.70603013185328E+175
	.sig	POINTER	[64760018H]
	.size	INTEGER	2287288
	.sp	INTEGER	256
	.typ	POINTER	NIL
 Meta.Item.ParamCallVal   [00002B5EH] 
	.adr	INTEGER	1685454913
	.data	ARRAY 256 OF INTEGER	elements

Crystal

Crystal doesn't have an assert statement. the spec module provides a testing DSL, but a simple assert can be created with a function or macro.

<lang ruby>class AssertionError < Exception end

def assert(predicate : Bool, msg = "The asserted condition was false")

 raise AssertionError.new(msg) unless predicate

end

assert(12 == 42, "It appears that 12 doesn't equal 42")</lang>

D

<lang d>import std.exception: enforce;

int foo(in bool condition) pure nothrow in {

   // Assertions are used in contract programming.
   assert(condition);

} out(result) {

   assert(result > 0);

} body {

   if (condition)
       return 42;
   // assert(false) is never stripped from the code, it generates an
   // error in debug builds, and it becomes a HALT instruction in
   // -release mode.
   //
   // It's used as a mark by the D type system. If you remove this
   // line the compiles gives an error:
   //
   // Error: function assertions.foo no return exp;
   //   or assert(0); at end of function
   assert(false, "This can't ha