North Airlines OO (2020) Unit 3 Blog Job

Catalog

JML Language Summary

theoretical basis

JML is a representation language used to standardize the design of Java programs. It uses JavaDoc comments to represent specifications.JML is based on Java syntax and has some extensions.The syntax of JML is divided into several levels. Here is a brief summary of the core features of JML Level 0.

Declarations of specification variables

Specification variables are divided into static specification variables and instance specification variables.In the case of integer arrays, they can be declared /@public static model non_null int []elements and //@public instance model non_null int []elements.

Common Expressions

Expression Meaning
\result Return value of non-void type methods
\old(expr) The value of an expression expr before the corresponding method is executed (following the reference rules)
\not_assigned(x, y, ...) Is the variable in parentheses not assigned during method execution
\not_modified(x, y, ...) The values of variables in restriction brackets do not change during method execution
(\forall T x; R(x); P(x)) Universal quantifier, indicating that x satisfying R(x) satisfies P(x)
(\exists T x; R(x); P(x)) Existential quantifier, indicating the presence of X satisfying R(x) P(x)
(\sum T x; R(x); expr) For X that satisfies R(x), sum expr
(\max T x; R(x); expr) For X that satisfies R(x), find the maximum expr
(\min T x; R(x); expr) For X that satisfies R(x), find the minimum value of expr
<==> Equivalent Operator
==> Implication operator
\nothing Empty set

Method Specification

The method specification can be divided into normal behavior specification and abnormal behavior specification, which correspond to normal_behavior and exceptional_behavior.Also connections are used between specifications.Each specification can also be divided into preconditions, scope limitations for side effects, and postconditions, corresponding to requires, assignable, and ensures, respectively.There is a conjunctive relationship between multiple clauses.

For purely accessible methods, there are no changes to the state of the object, no input parameters to provide, no preconditions to describe, no side effects to any such methods, and the execution will end normally.For such methods, you can describe their specifications in a simple (lightweight) way, using the pure keyword.In the method specification, preconditions can reference the results returned by the pure method.

For exception behavior specifications, we usually use signals or signals_only clause to throw an exception.The structure of the signals clause is signals (***Exception e) expr; meaning that when expr is true, the method throws the corresponding exception e given in parentheses;The only clause is structured as signals_only ***Exception; means that once this clause is entered, the corresponding exception will be thrown.

Type specification

The restriction rules that a type specification pointer designs for data types defined in Java programs are, in general, the restriction rules that the pointer designs for classes or interfaces.The focus of the course is invariant and state change constraint.The invariant invariant is a feature that must be satisfied in all visible states, while the state change constraint constraints constraints constrain the state change of an object.

Application Tool Chain Situation

The tool chain for JML is imperfect and largely has not been maintained for a long time.Common JML tools include OpenJML (syntax check for JML, simple static validation with Solver, and runtime validation), JMLUnitNG (automated unit test generation tool), and JMLUnit (similar to the former).OpenJML has an Eclipse plug-in version and has a good experience.However, it is a pity that there are no IDEA plug-ins available.

stayHttp://www.eecs.ucf.edu/~leavens/JML//download.shtmlThere are more descriptions of JML-related tools on this page.

OpenJML validation

Since the last two jobs cannot pass the syntax check of OpenJML, the following is an example of the first job to demonstrate OpenJML validation.

Parsing and Type-checking

This function mainly checks the syntax of the JML specification.

In IDEA's External Tools, run the following command:java-jarOpenjml.jar-check'$FilePath$'- CP'$Classpath$' - sourcepath'$Sourcepath$'- encoding UTF-8 to check the static syntax of the JML.The -check parameter specifies that the check type is Parsing and Type-checking, the -cp and -sourcepath commands specify the Classpath and source file directories, and the -encoding parameter specifies the file encoding.

The JML specification for the first job passed this check successfully with a return value of 0.

Extended Static Checking

This function mainly makes use of Solver to do simple static checks on programs written in JML.

In IDEA's External Tools, run the following command:java-jarOpenjml.jar-prover z3_4_7 - exec'. \Solvers-windows\z3-4.7.1.exe'- ESC'$FilePath$' - CP'$Classpath$'- sourcepath'$Sourcepath$' - encoding utf-8, you can do static syntax checking for JML.The -prover parameter specifies the Solver type, the -exec parameter specifies the Solver executable, and the -esc parameter specifies the Extended Static Checking check type.

Thirty-six warnings were triggered during the MyPerson check, mainly The prover cannot establish an assertion, but these warnings do not appear to be due to program errors, but to Solver's inability to adequately resolve the program; 100 warnings were triggered during the MyNetwork check, mainly The prover cannot establish an assertionAssertion, and prompts that static checking does not support pairing\not_The assigned expression checks.Thus, the support of this function for some more complex programs is still very lacking.

Here are some of the MyPerson class checks:

.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:82: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:67: notes: ) in method compareTo
return name.compareTo(p2.getName());
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:67: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:82: notes:
@ ensures \result == name.compareTo(p2.getName());
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:82: warning: The prover cannot establish an assertion (ExceptionalPostcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:66: notes: ) in method compareTo
return name.compareTo(p2.getName());
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:66: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:82: notes:
@ public normal_behavior
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:53: warning: The prover cannot establish an assertion (ExceptionalPostcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:29: notes: ) in method equals
return id == person.getId();
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:29: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:53: notes:
@ public normal_behavior
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:53: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:32: notes: ) in method equals
return id == person.getId();
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:32: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:53: notes:
@ ensures \result == (((Person) obj).getId() == id);
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:77: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:62: notes: ) in method getAcquaintanceSum
return acquaintance.size();
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:62: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:77: notes:
//@ ensures \result == acquaintance.length;
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:41: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:25: notes: ) in method getAge
return age;
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:25: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:41: notes:
//@ ensures \result == age;
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:36: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:22: notes: ) in method getCharacter
return character;
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:22: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:36: notes:
//@ ensures \result.equals(character);
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:26: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:16: notes: ) in method getId
return id;
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:16: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:26: notes:
//@ ensures \result == id;
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:31: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:19: notes: ) in method getName
return name;
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:19: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:31: notes:
//@ ensures \result.equals(name);
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:67: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:43: notes: ) in method isLinked
return id == person.getId() || acquaintance.containsKey(person);
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:43: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:67: notes:
@ ensures \result == (\exists int i; 0 <= i && i < acquaintance.length;
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:67: warning: The prover cannot establish an assertion (ExceptionalPostcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:41: notes: ) in method isLinked
return id == person.getId() || acquaintance.containsKey(person);
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:41: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:67: notes:
/@ public normal_behavior
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: warning: The prover cannot establish an assertion (ExceptionalPostcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:55: notes: ) in method queryValue
return acquaintance.getOrDefault(person, 0);
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:55: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: notes:
@ public normal_behavior
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: warning: The prover cannot establish an assertion (ExceptionalPostcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:48: notes: ) in method queryValue
return acquaintance.getOrDefault(person, 0);
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:48: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: notes:
/











@ public normal_behavior
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:58: notes: ) in method queryValue
return acquaintance.getOrDefault(person, 0);
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:58: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: notes:
@ ensures \result == 0;
^
.\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: warning: The prover cannot establish an assertion (Postcondition: .\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:52: notes: ) in method queryValue
return acquaintance.getOrDefault(person, 0);
^
.\Unit3Homework1\src\com\oocourse\spec1\main\Person.java:52: warning: Associated declaration: .\Unit3Homework1\src\com\oocourse\implements1\MyPerson.java:72: notes:
@ ensures (\exists int i; 0 <= i && i < acquaintance.length;
^












































































Runtime Assertion Checking

This function mainly makes simple runtime checks for programs written in JML.

In IDEA's External Tools, run the following command:java-jarOpenjml.jar-rac'$FilePath$'- CP'$Classpath$' - sourcepath'$Sourcepath$'- encoding UTF-8 to perform runtime checks for JML programs.The -rac parameter specifies that the check type is Runtime Assertion Checking.

OpenJML triggered an Internal JML bug during the MyPerson check and threw a NullPointerException; an error occurred during the MyNetwork check: An internal JML error occurred.Therefore, the function is not perfect.

JMLUnitNG test (for MyGroup class)

Start with OpenJML Jmlruntime.jarCopy to the directory where the environment variable CLASSPATH is located, then run the following command in the project directory: java-jar jmlunitng-1_4.jar-d. \test. \src to generate test classes.

For MyGroup class tests, MyGroup_can be run directlyJML_The main method in the Test class yields the following results:

[TestNG] Running:
Command line suite

Failed: racEnabled()
Passed: constructor MyGroup(-2147483648)
Passed: constructor MyGroup(0)
Passed: constructor MyGroup(2147483647)
Failed: <com.oocourse.implements3.MyGroup@8000001f>.addPerson(null)
Failed: <com.oocourse.implements3.MyGroup@1f>.addPerson(null)
Failed: <com.oocourse.implements3.MyGroup@8000001e>.addPerson(null)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.addRelation(-2147483648)
Passed: <com.oocourse.implements3.MyGroup@1f>.addRelation(-2147483648)
Passed: <com.oocourse.implements3.MyGroup@8000001e>.addRelation(-2147483648)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.addRelation(0)
Passed: <com.oocourse.implements3.MyGroup@1f>.addRelation(0)
Passed: <com.oocourse.implements3.MyGroup@8000001e>.addRelation(0)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.addRelation(2147483647)
Passed: <com.oocourse.implements3.MyGroup@1f>.addRelation(2147483647)
Passed: <com.oocourse.implements3.MyGroup@8000001e>.addRelation(2147483647)
Failed: <com.oocourse.implements3.MyGroup@8000001f>.delPerson(null)
Failed: <com.oocourse.implements3.MyGroup@1f>.delPerson(null)
Failed: <com.oocourse.implements3.MyGroup@8000001e>.delPerson(null)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.equals(null)
Passed: <com.oocourse.implements3.MyGroup@1f>.equals(null)
Passed: <com.oocourse.implements3.MyGroup@8000001e>.equals(null)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.equals(java.lang.Object@61baa894)
Passed: <com.oocourse.implements3.MyGroup@1f>.equals(java.lang.Object@b065c63)
Passed: <com.oocourse.implements3.MyGroup@8000001e>.equals(java.lang.Object@768debd)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getAgeMean()
Passed: <com.oocourse.implements3.MyGroup@1f>.getAgeMean()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getAgeMean()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getAgeVar()
Passed: <com.oocourse.implements3.MyGroup@1f>.getAgeVar()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getAgeVar()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getConflictSum()
Passed: <com.oocourse.implements3.MyGroup@1f>.getConflictSum()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getConflictSum()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getId()
Passed: <com.oocourse.implements3.MyGroup@1f>.getId()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getId()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getPeopleSum()
Passed: <com.oocourse.implements3.MyGroup@1f>.getPeopleSum()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getPeopleSum()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getRelationSum()
Passed: <com.oocourse.implements3.MyGroup@1f>.getRelationSum()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getRelationSum()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.getValueSum()
Passed: <com.oocourse.implements3.MyGroup@1f>.getValueSum()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.getValueSum()
Passed: <com.oocourse.implements3.MyGroup@8000001f>.hasPerson(null)
Passed: <com.oocourse.implements3.MyGroup@1f>.hasPerson(null)
Passed: <com.oocourse.implements3.MyGroup@8000001e>.hasPerson(null)
Passed: <com.oocourse.implements3.MyGroup@8000001f>.hashCode()
Passed: <com.oocourse.implements3.MyGroup@1f>.hashCode()
Passed: <com.oocourse.implements3.MyGroup@8000001e>.hashCode()


















































===============================================
Command line suite
Total tests run: 52, Failures: 7, Skips: 0

===============================================

Process finished with exit code 0

As you can see, JMLUnitNG is primarily tested for boundary data and null references.In the above test, the method failed mainly because it passed in null.The method is not handled in the code because it does not pass in null in this unit job.

Job Architecture Analysis

In this unit of work, I build mainly on JML and take some implementation optimization, such as applying containers and algorithms.In this unit, I don't do much abstraction, I just wrote the Pair and SementTree tool classes, and the Dijkstra and Point BiconnectedComponent internal classes in the MyNetwork class for encapsulating algorithms.I think it might be better to abstract the Graph and Node classes and have the MyNetwork and MyPerson classes inherit or combine them, respectively.

Here is the UML class diagram for the third job in this unit (the official package is omitted):

Job Bug Situation

There are no bug s in public and reciprocal tests for this unit operation.

In the second job, I tested locally and found that when the getAgeVar method in Group simplifies calculations using a variance formula, extracting items in parentheses can cause errors as follows:

public int getAgeVar() {
    if (people.isEmpty()) {
        return 0;
    }
    return (ageSquaredSum - 2 * getAgeMean() * ageSum) / people.size()
            + getAgeMean() * getAgeMean();
}

The following wording needs to be changed:

public int getAgeVar() {
    if (people.isEmpty()) {
        return 0;
    }
    return (ageSquaredSum - 2 * getAgeMean() * ageSum
            + getAgeMean() * getAgeMean() * people.size()) / people.size();
}

It has been proven that Java integer division rounds to zero, whereas negative numbers in parentheses written earlier may result in rounding errors that differ by 1 from the correct result.

Experience: Specification Writing and Understanding

In this unit, I have come into contact with a new programming mode: standardized design.Normalized design can separate the design from the implementation, and at the same time, the formal specification can facilitate strict formal verification.

When writing a specification, we think more about the design of the program from a demand perspective than from an implementation perspective.In addition, the preconditions of the specification prompt us to consider various boundary conditions and extreme data, alleviating the bugging of the program due to improper preconditions.

When understanding a specification, the focus is on understanding the behavior of the specification.Normally, specification descriptions are not appropriate to be implemented directly as code.Therefore, we need to understand the behavior described by the specification and choose the appropriate implementation.We can even further abstract on the basis of specifications to design a clearer and more reasonable program architecture.

Although such a rigorous and tedious formal specification is not common in the development of everyday software, I believe it will be useful in the field of high reliability because it can be rigorously formalized.

Tags: Java encoding Eclipse Windows

Posted on Tue, 19 May 2020 20:00:26 -0400 by LordPsyan