Constructor Institute of Technology Reif — Research Eiffel

Verification of basic properties

To prove functional correctness automatically, a program needs a machine- readable specification. We are using Eiffel — an object-oriented programming language — which allows one to write contracts as part of the program. Each Eiffel routine is equipped with pre- and postconditions and each class has a class invariant.

We will use the Account example to show the basic concepts of Auto- Proof. The example consists of the two classes ACCOUNT and ACCOUNT_TEST. The first class models a bank account and the second class consists of two test cases that show proper and improper usage of the class. The full code of class ACCOUNT is shown below.

note
  description: "Account class."
  model: balance, credit_limit

class ACCOUNT
create make

feature {NONE} -- Initialization

  make
	  -- Initialize empty account.
  note
	status: creator
  do
	balance := 0
	credit_limit := 0
  ensure
	balance_set: balance = 0
	credit_limit_set: credit_limit = 0
  end

feature -- Access

  balance: INTEGER
	  -- Balance of this account.

  credit_limit: INTEGER
	  -- Credit limit of this account.

  available_amount: INTEGER
	  -- Amount available on this account.
	note
	  status: functional
	do
	  Result := balance + credit_limit
	end

feature -- Element change

  set_credit_limit (limit: INTEGER)
	  -- Set ‘credit_limit’ to ‘limit’.
	require
	  limit_valid: limit  (0).max(balance)
	  modify_model ("credit_limit", Current)
	do
	  credit_limit := limit
	ensure
	  credit_limit_set: credit_limit = limit
	end

  deposit (amount: INTEGER)
	  -- Deposit ‘amount’ in this account.
	require
	  amount_non_negative: amount  0
	  modify_model ("balance", Current)
	do
	  balance := balance + amount
	ensure
	  balance_set: balance = old balance + amount
	end

  withdraw (amount: INTEGER)
	  -- Withdraw ‘amount’ from this account.
	require
	  amount_not_negative: amount  0
	  amount_available: amount  available_amount
	  modify_field (["balance", "closed"], Current)
	do
	  balance := balance  amount
	ensure
	  balance_set: balance = old balance  amount
	end

feature -- Basic operations

  transfer (amount: INTEGER; other: ACCOUNT)
	  -- Transfer ‘amount’ from this to ‘other’.
	require
	  amount_not_negative: amount  0
	  amount_available: amount  available_amount
	  no_aliasing: other 6 = Current
	  modify (Current, other)
	do
	  balance := balance  amount
	  other.deposit (amount)
	ensure
	  balance = old balance  amount
	  other.balance = old other.balance + amount
	  credit_limit = old credit_limit
	  other.credit_limit = old other.credit_limit
	end

invariant
  limit_not_negative: credit_limit  0
  balance_not_credit: balance  credit_limit

end

First you can look through the example and verify the two classes; all routines, except for the deliberately failing test case, will be successfully verified.