Exercises with JML and ESC/Java2

Taxpayer exercise

Part 1

Download the file Taxpayer.java. This Java class is used in an information system at the tax office to record information about persons. The tax office wants to ensure that the following properties hold:
  1. Persons are either male or female.
  2. Persons can only marry to people of the opposite sex. (A bit outdated maybe, but makes for interesting properties to specify).
  3. A very obvious property, but easy to overlook: if person x is married to person y, then person should of course also be married, and to person x.
Your assignment is to
  1. add invariants to the code below to express the properties mentioned above, in JML syntax, plus any other sensible properties you can think of;
  2. use ESC/Java2 to detect possible violations, which are reported as warnings
  3. for the Java methods that ESC/Java2 complains about fix this, by
    1. correcting the code, or
    2. adding a (sensible) precondition for the method, using a JML requires clause, or
    3. sometimes, adding an invariant to record another property can help in verification.
Hints In the end, ESC/Java2 should run without any complaints on the annotated code, meaning that it has succeeded in verifying that the code meets the formal specification.

JML syntax

Below the syntax for Java and JML logical connectives, in order of decreasing precedence:

logical connective    Java/JML syntax
not !
equality ==
inquality !=
conjunction (and) &&
disjunction (or) ||
implication ==> , <==
(in)equivalence <==> , <=!=>
In addition to this, you can use standard Java syntax, so you can say things such as

  this.spouse != null ==>
    (this.spouse.spouse.isFemale ==> this.isFemale)
Of course, you can write spouse instead of this.spouse, leaving this implicit. Note that in Java, as in most programming languages, references such as the spouse field, can be null. Often fields should not be null under certain circumstances, which can be expressed by an invariant of the form
 //@ invariant  .... ==> spouse !=null;
Often arguments of method should not be null, which can be expressed by a precondition of the form
 //@ requires new_spouse != null;
 void marry (Taxpayer new_spouse) {

Part 2

The tax system uses an income tax allowance (in Dutch: belastingvrije voet):
  1. Every person has an income tax allowance, over which means they do not have to pay tax over the first part of their income. There is a default tax allowance of 5000.
  2. Married persons can pool their tax allowance, as long as the sum of their tax allowances remains the same. For example, the wife could have a tax allowance of 10000, and the husband a tax allowance of 0.
Add invariants that express these constraints, and if necessary fix/improve the code to ensure that they are not violated.


Part 3

The new government introduces a measure that people aged 65 and over have a higher tax allowance, of 7000. The rules for pooling tax allowances remain the same.

Add invariants that express these constraints, and if necessary fix/improve the code to ensure that they are not violated.


Part 4

WARNING: things may get a bit hairy here, so don't be too depressed if you don't manage to finish this.

The minister for Jeugd en Gezin, André Rouvoet, introduces a new tax measure giving anyone with underage children an additional tax allowance of 1000 euro.

The taxpayer class is extended with an additional field to keep track of the youngest child

   Taxpayer youngestChild;    // youngest child of this person
and the following three lines are added to the constructor
   Taxpayer(boolean jongetje, Taxpayer mum, Taxpayer dad) {
      ...
      youngestChild = null;        // NEW
      mum.youngestChild = this;    // NEW
      dad.youngestChild = this;    // NEW
   }

Add the three lines above to your code, add invariant(s) to express the new government policy above, and re-run ESC/Java2 and fix the code to ensure that it is not violated.


General hints

Some hints to keep you out of trouble with the tool: