1. The theoretical basis and application tool chain of JML
1. Theoretical basis
- Atomic expression
- \result: Represents the return value of a non-void method after execution.
- \old(expr): Indicates the value of an expression expr before executing the corresponding method
- \not_assigned(x, y,...): Indicates whether the variable in parentheses is assigned during method execution.Returns true if not assigned; false otherwise
- \not_modified(x, y,...): like not_assigned, the difference is whether the value of the variable changes
- \type(type): Class corresponding to return type type
- Quantitative expression
- \forall:An expression modified by a universal quantifier that indicates that each element within a given range satisfies a corresponding constraint
- \exists: There is a quantifier-modified expression that expresses that for elements within a given range, there is an element that satisfies the corresponding constraint
- \sum: Returns the sum of expressions in a given range
- \max and min: Returns the maximum and minimum values of expressions within a given range, respectively
- Method Specification
- Preconditions: Preconditions are represented by a requires clause: requires P, which requires that condition P be true
- Postcondition: Postcondition is represented by the ensures clause: ensures P, which requires that the method execution return result must satisfy the predicate P
- Side effect limitation: assignable and modifiable, respectively, indicate assignable and modifiable
- Type specification
- Invariant invariant: is a feature that must be satisfied in all visible states, invariant P
- State change constraint: Constrains the relationship between the prefix visible state and the current visible state
2. Tool Chain Application
1.OpenJML: You can check the JML document specification syntax, where SMT Solver can verify that the code meets the specification
2.JMLUnitNG: A JML-based unit test tool that automatically generates test cases
3.Junit: Used for unit testing, automated tests that can be written and run repeatedly.
According to Mr. Jiao's blog, I entered the following four codes:
java -jar jmlunitng.jar jmlunit/MyGroup.java javac -cp jmlunitng.jar jmlunit/*.java java -jar openjml.jar -rac jmlunit/MyGroup.java java -cp jmlunitng.jar jmlunit.MyGroup_JML_Test
The results are as follows:
[TestNG] Running: Command line suite Passed: racEnabled() Passed: constructor MyGroup(-2147483648) Passed: constructor MyGroup(0) Passed: constructor MyGroup(2147483647) Failed: <<MyGroup@4ebba42a>>.addPerson(null) Failed: <<MyGroup@467eca23>>.addPerson(null) Passed: <<MyGroup@66133adc>>.delPerson(null) Failed: <<MyGroup@287534f5>>.delPerson(null) Failed: <<MyGroup@ba4d4a7e>>.delPerson(null) Passed:<<MyGroup@5c0e39b3>>.equals(null) Passed:<<MyGroup@d793cb21>>.equals(null) Passed:<<MyGroup@508a4bba>>.equals(null) Passed: <<MyGroup@a2b1398c>>.equals(java.lang.Object@574caa3f) Passed: <<MyGroup@63bcaa71>>.equals(java.lang.Object@64cee07) Passed: <<MyGroup@2d7f89e3>>.equals(java.lang.Object@1761e840) Passed: <<MyGroup@23fea612>>.getAgeMean() Passed: <<MyGroup@b45e2fa7>>.getAgeMean() Passed: <<MyGroup@685b3ad2>>.getAgeVar() Passed: <<MyGroup@3536c874>>.getAgeVar() Passed: <<MyGroup@c2f309a6>>.getAgeVar() Passed: <<MyGroup@ab27c89c>>.getConflictSum() Passed: <<MyGroup@1ef7015a>>.getConflictSum() Passed: <<MyGroup@74b8b58f>>.getConflictSum() Passed: <<MyGroup@1c56bc89>>.getId() Passed: <<MyGroup@445a8ca1>>.getId() Passed: <<MyGroup@38b6c32a>>.getId() Passed: <<MyGroup@3ae8b12a>>.getRelationSum() Passed: <<MyGroup@3e2851ac>>.getRelationSum() Passed: <<MyGroup@a93c83c7>>.getValueSum() Passed: <<MyGroup@721f0239>>.getValueSum() Passed: <<MyGroup@6ab01c56>>.getValueSum() Failed: <<MyGroup@1f6ff78c>>.hasPerson(null) Failed: <<MyGroup@c81f7a90>>.hasPerson(null) Failed: <<MyGroup@48e75ac0>>.hasPerson(null) Passed: <<MyGroup@5e876f2a>>.updatePerson(null) Passed: <<MyGroup@6f91e371>>.updatePerson(null) Passed: <<MyGroup@b274b4d7>>.updatePerson(null) Passed: <<MyGroup@13fa6a7b>>.downloadPerson(null) Passed: <<MyGroup@49a3b226>>.downloadPerson(null) Passed: <<MyGroup@6821a38b>>.downloadPerson(null) Failed: <<MyGroup@21ab83e5>>.updateLink(null, null) Failed: <<MyGroup@48e2ff12>>.updateLink(null, null) Failed: <<MyGroup@67a8815e>>.updateLink(null, null) =============================================== Command line suite Total tests run: 43, Failures: 12, Skips: 0 ===============================================
* Feels that the data generated by jmlunitng is very extreme and less useful.And I have to say that deploying solver and jmlunitng is very cumbersome and prone to a wide variety of metaphysical problems. In conclusion, I do not think it is very practical.
3. Architecture Design of Jobs
1. First job
The first operation is simple, just use bfs to prevent the stack from exploding.
2. Second job
The main optimization direction is to use the cache to optimize the two-tier loop.
3. Third Operation
4. bug analysis
1. First job
The first operation is relatively simple and there are no bug s in both mandatory and cross-testing.
2. Second job
I did not have any bugs in the second test.Other hack points are time-out bugs, some students do not use the cache mechanism to store the appropriate state values to save computing time, perhaps because of better luck in the strong test into House A, and then it is obviously impossible to survive the cross-test.Because the complexity of the two-tier loop is obviously too high, it is not difficult to get a card.
3. Third Operation
- I was stuck in a timeout during the third exercise of the maneuver and cross-test.Since I used the general Dijkstra algorithm after class and did not use cache and heap optimization to speed up, it was really complex and time-out was easy.I timed out at five points in the quiz.
- In mutual testing, some people have judged that point dual connectivity is achieved by enumerating all paths, and I have built a graph with a very large number of paths, which makes the time complexity of students using this method very high and easy to time out.
5. Related Feelings
1. I personally feel that the debug method for this unit is very different from the previous two units.
The main debug methods I think are the following:
- Find a goofy code, randomly generate test data, and beat
- Using the python-specific graph theory library networkx
- jmlunitng,solver, etc.
In a few ways, I find junit the least reliable.Although junit is really convenient to iterate over TDD, we wrote our own test samples. As far as I know, many bug s in this unit are caused by not seeing the specifications clearly, and junit obviously can't solve them.
I personally admire this method of filming with Big Guy Code, first of all I do it myself, and secondly it is really very effective. I help others and myself find bug s.The most important thing is that this unit writes very well on the photos, considering that the result is the only decision. Unlike elevator units, there are many correct answers that make the writing of the photos more complex.
I think the networkx library is a good way to do that. This graph theory library has to be said to be very powerful. The most complex functions in many jobs can be tested very well with just one statement from python.
jmlunitng,solver, etc. I don't recommend debug because I find it very complex to configure and can't perform as effectively as debug.
2.python library neyworkx
As mentioned above, some very complex functions can be perfectly tested with only one statement, such as:
- Determine Connectivity:nx.haspath()
Point Double Connectivity:nx.biconnected_components(G)
Find all disconnected subgraphs:connected_components(G).(
I think the combination of nerworkx and matlabplot is very good. For example, the graphics of hack points in the mandatory or cross-test are more complex. If it is obviously unrealistic to draw by hand, you can use the two tools together to draw clear and beautiful graphics, as shown in the following figure: