/* * Quasar: lightweight threads and actors for the JVM. * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.fibers.instrument; import co.paralleluniverse.common.util.SystemProperties; import co.paralleluniverse.fibers.Fiber; import co.paralleluniverse.fibers.SuspendExecution; import co.paralleluniverse.fibers.Suspendable; import co.paralleluniverse.fibers.VerifyInstrumentationException; import co.paralleluniverse.strands.SuspendableCallable; import co.paralleluniverse.strands.SuspendableRunnable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; import static org.junit.Assume.*; import co.paralleluniverse.strands.channels.Channels; import co.paralleluniverse.strands.channels.IntChannel; import org.junit.Test; /** * * @author circlespainter */ public final class VerificationTest { interface I1 { void doIt(); } @Suspendable interface I2 { void doIt(); } private static abstract class A1 { protected abstract void doItAbstr(); } private static abstract class A2 { protected abstract void doItAbstr1(); @Suspendable protected abstract void doItAbstr2(); } private static final class C1 extends A1 implements I1, I2 { @Override @Suspendable public final void doIt() { try { Fiber.sleep(10); } catch (final InterruptedException | SuspendExecution e) { throw new AssertionError(e); } } @Override @Suspendable protected final void doItAbstr() { try { Fiber.sleep(10); } catch (final InterruptedException | SuspendExecution e) { throw new AssertionError(e); } } } private static final class C2 extends A2 implements I1, I2 { @Override @Suspendable public final void doIt() { try { Fiber.sleep(10); } catch (final InterruptedException | SuspendExecution e) { throw new AssertionError(e); } } @Override @Suspendable protected final void doItAbstr1() { try { Fiber.sleep(10); } catch (final InterruptedException | SuspendExecution e) { throw new AssertionError(e); } } @Override @Suspendable protected final void doItAbstr2() { try { Fiber.sleep(10); } catch (final InterruptedException | SuspendExecution e) { throw new AssertionError(e); } } } private void doUninstrumented() throws Exception { Fiber.sleep(10); } private void doInstrumented() throws InterruptedException, SuspendExecution { Fiber.sleep(10); } @Test public final void testVerifyUninstrumentedMethod() throws ExecutionException, InterruptedException { assumeTrue(SystemProperties.isEmptyOrTrue("co.paralleluniverse.fibers.verifyInstrumentation")); final I1 i1 = new C1(); Throwable t = null; final Fiber<?> fUninstrumentedMethod1 = new Fiber<>(new SuspendableRunnable() { @Override public final void run() throws SuspendExecution, InterruptedException { try { doUninstrumented(); // ** Fiber.sleep(10); } catch (final Exception e) { throw new RuntimeException(e); } } }).start(); try { fUninstrumentedMethod1.join(); } catch (final ExecutionException re) { t = re.getCause().getCause(); t.printStackTrace(); } assertTrue(t instanceof VerifyInstrumentationException && t.getMessage().contains(" **")); final Fiber<?> fUninstrumentedMethod2 = new Fiber(new SuspendableRunnable() { @Override public final void run() throws SuspendExecution, InterruptedException { try { i1.doIt(); } finally { i1.doIt(); } } }).start(); try { fUninstrumentedMethod2.join(); } catch (final ExecutionException re) { t = re.getCause(); t.printStackTrace(); } assertTrue(t instanceof VerifyInstrumentationException && t.getMessage().contains(" **")); } @Test public final void testVerifyUninstrumentedCallSite() throws ExecutionException, InterruptedException { assumeTrue(SystemProperties.isEmptyOrTrue("co.paralleluniverse.fibers.verifyInstrumentation")); final I1 i1 = new C1(); final A1 a1 = (C1) i1; Throwable t = null; final Fiber<?> fUninstrumentedCallSite1 = new Fiber<>(new SuspendableRunnable() { @Override public final void run() throws SuspendExecution, InterruptedException { try { Fiber.sleep(10); i1.doIt(); // !! } finally { i1.doIt(); } }}).start(); try { fUninstrumentedCallSite1.join(); } catch (final ExecutionException re) { t = re.getCause(); t.printStackTrace(); } assertTrue(t instanceof VerifyInstrumentationException && t.getMessage().contains(" !! (")); final Fiber<?> fUninstrumentedCallSite2 = new Fiber<>(new SuspendableRunnable() { @Override public final void run() throws SuspendExecution, InterruptedException { try { Fiber.sleep(10); a1.doItAbstr(); // !! } finally { a1.doItAbstr(); } }}).start(); try { fUninstrumentedCallSite2.join(); } catch (final ExecutionException re) { t = re.getCause(); t.printStackTrace(); } assertTrue(t instanceof VerifyInstrumentationException && t.getMessage().contains(" !! (")); } @Test public final void testVerifyUninstrumentedCallSiteSameSourceLine() throws ExecutionException, InterruptedException { assumeTrue(SystemProperties.isEmptyOrTrue("co.paralleluniverse.fibers.verifyInstrumentation")); final A2 a2 = new C2(); Throwable t = null; final Fiber<?> fUninstrumentedCallSite3 = new Fiber<>(new SuspendableRunnable() { @Override public final void run() throws SuspendExecution, InterruptedException { try { Fiber.sleep(10); a2.doItAbstr1(); a2.doItAbstr2(); // !! } finally { a2.doItAbstr1(); a2.doItAbstr2(); } }}).start(); try { fUninstrumentedCallSite3.join(); } catch (final ExecutionException re) { t = re.getCause(); t.printStackTrace(); } assertTrue(t instanceof VerifyInstrumentationException && t.getMessage().contains(" !! (")); } @Test public final void testVerificationOK() throws ExecutionException, InterruptedException { final I1 i1 = new C1(); final I2 i2 = (C1) i1; final Fiber<Integer> fOk = new Fiber<>(new SuspendableCallable<Integer>() { @Override public final Integer run() throws SuspendExecution, InterruptedException { Fiber.sleep(10); i2.doIt(); doInstrumented(); return 4; }}).start(); assertEquals(fOk.get(), new Integer(4)); } @Test public final void testVerifyUninstrumentedCallSiteDeclaringAndOwnerOK() throws ExecutionException, InterruptedException, SuspendExecution { assumeTrue(SystemProperties.isEmptyOrTrue("co.paralleluniverse.fibers.verifyInstrumentation")); // From https://github.com/puniverse/quasar/issues/255 final IntChannel intChannel = Channels.newIntChannel(1); try { new Fiber<>(new SuspendableCallable<Integer>() { @Override public Integer run() throws SuspendExecution, InterruptedException { return intChannel.receive(); } }).start().join(100, TimeUnit.MILLISECONDS); } catch (final TimeoutException ignored) { } // Should complete without verification exceptions } }