Mercurial > hg > Members > kono > jpf-core
view src/tests/gov/nasa/jpf/test/mc/threads/RaceTest.java @ 0:61d41facf527
initial v8 import (history reset)
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Fri, 23 Jan 2015 10:14:01 -0800 |
parents | |
children |
line wrap: on
line source
/* * Copyright (C) 2014, United States Government, as represented by the * Administrator of the National Aeronautics and Space Administration. * All rights reserved. * * The Java Pathfinder core (jpf-core) platform is licensed under the * Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * this is a raw test class for detection of thread-shared fields, i.e. * it executes the garbage collection based reachability analysis */ package gov.nasa.jpf.test.mc.threads; import gov.nasa.jpf.util.TypeRef; import gov.nasa.jpf.util.test.TestJPF; import org.junit.Test; class SharedObject { int instanceField; int whatEver; } public class RaceTest extends TestJPF { static final TypeRef PROPERTY = new TypeRef("gov.nasa.jpf.listener.PreciseRaceDetector"); static final String LISTENER = "+listener=gov.nasa.jpf.listener.PreciseRaceDetector"; static int staticField; @Test public void testStaticRace () { if (verifyUnhandledException("java.lang.RuntimeException")) { Runnable r1 = new Runnable() { @Override public void run() { staticField = 1; if (staticField != 1) { throw new RuntimeException("r1 detected race!"); } } }; Runnable r2 = new Runnable() { @Override public void run() { staticField = 0; if (staticField != 0) { throw new RuntimeException("r2 detected race!"); } } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } @Test public void testStaticRaceNoThrow () { if (verifyPropertyViolation(PROPERTY, LISTENER)) { Runnable r1 = new Runnable() { @Override public void run() { staticField = 1; } }; Runnable r2 = new Runnable() { @Override public void run() { staticField = 0; } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } // this represents the case where the class loading thread is non-deterministic static class Container { static int data; // that's what we race for } static class StaticRacer extends Thread { @Override public void run(){ Container.data++; } } @Test public void testSymmetricStaticRace(){ if (verifyUnhandledExceptionDetails("java.lang.RuntimeException", "got race", "+vm.scheduler.sharedness.class=.vm.GlobalSharednessPolicy")) { StaticRacer t1 = new StaticRacer(); StaticRacer t2 = new StaticRacer(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException ix){ fail("got interrupted"); } if (Container.data != 2){ System.out.print("Container.data = "); System.out.print( Container.data); System.out.println(" => throwing RuntimeException"); throw new RuntimeException("got race"); } } } @Test public void testInstanceRace () { if (verifyUnhandledException("java.lang.RuntimeException")) { final SharedObject o = new SharedObject(); Runnable r1 = new Runnable() { SharedObject d = o; @Override public void run() { d.instanceField = 1; if (d.instanceField != 1) { throw new RuntimeException("r1 detected race!"); } } }; Runnable r2 = new Runnable() { SharedObject d = o; @Override public void run() { d.instanceField = 0; if (d.instanceField != 0) { throw new RuntimeException("r2 detected race!"); } } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } @Test public void testInstanceRaceNoThrow () { if (verifyPropertyViolation(PROPERTY, LISTENER)) { final SharedObject o = new SharedObject(); Runnable r1 = new Runnable() { SharedObject d = o; @Override public void run() { d.instanceField = 1; } }; Runnable r2 = new Runnable() { SharedObject d = o; @Override public void run() { d.instanceField = 0; } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } @Test public void testInstanceRaceListenerExclude () { if (verifyNoPropertyViolation(LISTENER, "+race.exclude="+ RaceTest.class.getName() + "*")){ testInstanceRaceNoThrow(); } } @Test public void testInstanceRaceListenerInclude () { if (verifyPropertyViolation(PROPERTY, LISTENER, "+race.include=" + RaceTest.class.getName() + "*")){ testInstanceRaceNoThrow(); } } @Test public void testStaticRaceListenerIncludeOther () { if (verifyNoPropertyViolation(LISTENER, "+race.include=sho.bi.Doo*")){ testStaticRaceNoThrow(); } } @Test public void testArrayRaceNoThrow () { if (verifyPropertyViolation(PROPERTY, LISTENER, "+cg.threads.break_arrays")){ final int[] shared = new int[1]; Runnable r1 = new Runnable(){ int[] a = shared; @Override public void run() { a[0] = 0; } }; Runnable r2 = new Runnable(){ int[] a = shared; @Override public void run() { a[0] = 1; } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } /* * mostly the same as above except of that the race candidates are the same insn instance, i.e. use the same * cached insn fields values */ static class AT extends Thread { int[] a; int idx; AT (int[] a, int idx) { this.a = a; this.idx = idx; } @Override public void run (){ //assertTrue( a[idx] == 0); a[idx] = 1; } } @Test public void testNoArrayRaceSameInsn (){ if (verifyNoPropertyViolation(LISTENER, "+cg.threads.break_arrays")){ int[] a = new int[2]; AT t1 = new AT(a, 0); t1.start(); AT t2 = new AT(a, 1); t2.start(); } } // the dual @Test public void testArrayRaceSameInsn (){ if (verifyPropertyViolation(PROPERTY, LISTENER, "+cg.threads.break_arrays")){ int[] a = new int[2]; AT t1 = new AT(a, 1); t1.start(); AT t2 = new AT(a, 1); t2.start(); } } @Test public void testNoArrayRaceElements () { if (verifyNoPropertyViolation(LISTENER, "+cg.threads.break_arrays")){ final int[] shared = new int[2]; Runnable r1 = new Runnable(){ int[] a = shared; @Override public void run() { a[0] = 0; } }; Runnable r2 = new Runnable(){ int[] a = shared; @Override public void run() { a[1] = 1; } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } //--- these are tests to check false positives static class SameInsnRunnable implements Runnable { SharedObject o = new SharedObject(); @Override public void run () { o.instanceField = 42; // same insn, different 'o', no race } } @Test public void testSameInsnOtherObject () { if (verifyNoPropertyViolation(LISTENER)) { SameInsnRunnable r1 = new SameInsnRunnable(); SameInsnRunnable r2 = new SameInsnRunnable(); Thread t = new Thread(r1); t.start(); r2.run(); } } @Test public void testSameObjectOtherField() { if (verifyNoPropertyViolation(LISTENER)) { final SharedObject o = new SharedObject(); Runnable r = new Runnable() { @Override public void run() { o.instanceField = 42; } }; Thread t = new Thread(r); o.whatEver = -42; // different field, no race } } //--- try variations of locks class AnotherSharedObject { Object lock1 = new Object(); Object lock2 = new Object(); int x = 0; } @Test public void testNoSync() { if (verifyUnhandledException("java.lang.RuntimeException")) { final AnotherSharedObject o = new AnotherSharedObject(); Runnable r = new Runnable() { @Override public void run() { o.x++; if (o.x == 0) { throw new RuntimeException("testNoSync race"); } } }; Thread t = new Thread(r); t.start(); o.x--; } } @Test public void testTSync() { if (verifyUnhandledException("java.lang.RuntimeException")) { final AnotherSharedObject o = new AnotherSharedObject(); Runnable r = new Runnable() { @Override public void run() { synchronized (o.lock1) { o.x++; if (o.x == 0) { throw new RuntimeException("testT1Sync race"); } } } }; Thread t = new Thread(r); t.start(); // no sync o.x--; } } @Test public void testMainSync () { if (verifyUnhandledException("java.lang.RuntimeException")) { final AnotherSharedObject o = new AnotherSharedObject(); Runnable r = new Runnable() { @Override public void run() { // not synchronized o.x++; if (o.x == 0) { throw new RuntimeException("testMainSync race"); } } }; Thread t = new Thread(r); t.start(); synchronized (o.lock1) { o.x--; } } } @Test public void testBothSync () { if (verifyNoPropertyViolation()) { final AnotherSharedObject o = new AnotherSharedObject(); Runnable r = new Runnable() { @Override public void run() { synchronized (o.lock1) { o.x++; if (o.x == 0) { throw new RuntimeException("testBothSync race??"); } } } }; Thread t = new Thread(r); t.start(); synchronized (o.lock1) { o.x = 0; } } } @Test public void testWrongSync () { if (verifyUnhandledException("java.lang.RuntimeException")) { final AnotherSharedObject o = new AnotherSharedObject(); Runnable r = new Runnable() { @Override public void run() { synchronized (o.lock1) { o.x++; if (o.x == 0) { throw new RuntimeException("testWrongSync race"); } } } }; Thread t = new Thread(r); t.start(); synchronized (o.lock2) { o.x--; } } } }