The occurrence of potential errors in concurrent programs is not deterministic, but random.
Security testing: Usually in the form of test invariance conditions, that is, determining whether a class's behavior is consistent with its specifications
Activity testing: Both progress testing and non-progress testing are difficult to quantify (performance: throughput, responsiveness, scalability testing)
First, the correctness test
Focus: Identifying the conditions of invariance and posterior conditions to be examined
1. Test the basic unit-serial execution
1 public class Boundedbuffertests {2 3 @Test 4 public void Testisemptywhenconstructed () {5 boundedbuffer<string> bf = new boundedbuffer<string> (10); 6 Asserttrue (Bf.isempty ()); 7 } 8 9 @Test10 public void Testisfullafterputs () throws interruptedexception{11 boundedbuffer<string> bf = new boundedbuffer<string> ( int i= 0; i<10; i++) { bf.put ("" + i), }15 asserttrue (Bf.isfull ()), asserttrue (Bf.isempty ()); 18}
2, the test of blocking operation
Each test must wait until all the threads he has created end before it can end (join)
To test the blocking behavior of a method is similar to testing a method that throws an exception: If the method returns normally, it means that the test failed.
When testing the blocking behavior of a method, additional complexity is introduced: When the method is successfully blocked, the method must be unblocked. Interrupt
1 public void Testtaskblockswhenempty () {2 final boundedbuffer<integer> bb = new boundedbuffer<> (10); 3< C1/>thread taker = new Thread () {4 @Override 5 public void Run () {6 try {7 int unused = Bb.take (); 8 fail ();//should not be performed here 9 } catch (Interruptedexception e) {Ten }11 }12 };13 try { taker.start (); Thread.Sleep (+), taker.interrupt (), Taker.join (2000), or guaranteed to return to Assertfalse even if the taker is permanently blocked (taker.isalive ()); catch (Interruptedexception e) { fail (); }22}
3. Safety Test
The key issue that needs to be addressed when building security tests for concurrency classes is to identify those properties that are easy to examine, which are most likely to fail in the event of an error without causing the error-checking code to artificially limit concurrency. Ideally, no synchronization mechanism is required in the test properties
Example: by calculating the checksum of the into row and the check-out (using the fence to ensure that the thread is running to the inspection place)
4. Resource Management test
Any object that holds or manages other objects should destroy references to them when they are not needed
Example: Using the heap inspection tool to verify memory resource usage
5. Using callbacks
You can use custom extension classes for related tests
1 public class Testingthreadfactory implements Threadfactory {2 public final Atomicinteger numcreated = 3 NE W Atomicinteger (); Record number of threads created 4 private final Threadfactory factory = 5 executors.defaultthreadfactory (); 6 7 @ Override 8 public Thread Newthread (Runnable r) {9 numcreated.incrementandget (); Factory.newthread (R); }12}
6. Generate more alternating operations
Using yield, sleep commands makes it easier to make errors appear
Second, performance testing
Objectives of the performance test:
- Measure end-to-end performance in typical test cases to get a reasonable usage scenario
- Adjust various limits based on experience values, such as number of threads, cache capacity, etc.
1. Timer
Calculate run time by adding timers and changing individual parameters, thread pool size, cache size
Cases:
2. Comparison of multiple algorithms
Identify algorithms with higher scalability using different internal implementation algorithms
Cases:
3. Responsiveness Measurement
How long it takes a certain action to perform, the change in service time needs to be measured
Non-fair semaphores typically achieve better throughput unless the thread is continuously blocked due to dense synchronization requirements, while fair semaphores achieve lower variability (fairness overhead is mainly caused by thread blocking)
Iii. pitfalls of avoiding performance tests
1. Garbage collection
- Ensure that garbage collection is not executed during the execution of the test program, and that garbage collection information can be viewed through-VERBOSE:GC.
- Ensuring that garbage collection executes multiple times during the execution of a tester can fully reflect the overhead of memory allocation and garbage collection during run time.
2. Dynamic compilation
- You can have the test program run long enough to prevent dynamic compilation from deviating from the test results.
- Set-xx:+printcompilation in hotspot to output a piece of information at dynamic compile time
3, the code path is not true sampling
- Dynamic compilation can cause different code to be generated by the same method that is called in different places
- The test program not only roughly determines the usage pattern of a typical application, but also overwrites the collection of code paths that will be executed in the application.
4, the level of competition is not true
- Different levels of shared data and execution of local computing will show a different level of competition, with different performance and scalability
5, the elimination of useless code
- The compiler may delete code that is meaningless or does not produce results or predictable results
- Make the results as unpredictable as possible
Iv. Other test methods
Code review (Manual Check Code), Race Analysis tool (Findbugs,checkstyle), aspect-oriented testing techniques, analysis and detection tools (JVISUALVM)
Java Concurrency Programming: the 12th Chapter---test of concurrent programs