1 /* 2 * Copyright (C) 2014 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import static com.google.common.util.concurrent.GeneratedMonitorTest.startThread; 20 import static com.google.common.util.concurrent.Uninterruptibles.joinUninterruptibly; 21 import static org.junit.Assert.assertThrows; 22 23 import com.google.common.util.concurrent.GeneratedMonitorTest.FlagGuard; 24 import java.util.concurrent.atomic.AtomicBoolean; 25 import java.util.concurrent.atomic.AtomicInteger; 26 import java.util.concurrent.atomic.AtomicReference; 27 import junit.framework.TestCase; 28 29 /** 30 * Supplemental tests for {@link Monitor}. 31 * 32 * <p>This test class contains various test cases that don't fit into the test case generation in 33 * {@link GeneratedMonitorTest}. 34 * 35 * @author Justin T. Sampson 36 */ 37 public class SupplementalMonitorTest extends TestCase { 38 testLeaveWithoutEnterThrowsIMSE()39 public void testLeaveWithoutEnterThrowsIMSE() { 40 Monitor monitor = new Monitor(); 41 assertThrows(IllegalMonitorStateException.class, () -> monitor.leave()); 42 } 43 testGetWaitQueueLengthWithWrongMonitorThrowsIMSE()44 public void testGetWaitQueueLengthWithWrongMonitorThrowsIMSE() { 45 Monitor monitor1 = new Monitor(); 46 Monitor monitor2 = new Monitor(); 47 FlagGuard guard = new FlagGuard(monitor2); 48 assertThrows(IllegalMonitorStateException.class, () -> monitor1.getWaitQueueLength(guard)); 49 } 50 testHasWaitersWithWrongMonitorThrowsIMSE()51 public void testHasWaitersWithWrongMonitorThrowsIMSE() { 52 Monitor monitor1 = new Monitor(); 53 Monitor monitor2 = new Monitor(); 54 FlagGuard guard = new FlagGuard(monitor2); 55 assertThrows(IllegalMonitorStateException.class, () -> monitor1.hasWaiters(guard)); 56 } 57 testNullMonitorInGuardConstructorThrowsNPE()58 public void testNullMonitorInGuardConstructorThrowsNPE() { 59 assertThrows(NullPointerException.class, () -> new FlagGuard(null)); 60 } 61 testIsFair()62 public void testIsFair() { 63 assertTrue(new Monitor(true).isFair()); 64 assertFalse(new Monitor(false).isFair()); 65 } 66 testOccupiedMethods()67 public void testOccupiedMethods() { 68 Monitor monitor = new Monitor(); 69 verifyOccupiedMethodsInCurrentThread(monitor, false, false, 0); 70 verifyOccupiedMethodsInAnotherThread(monitor, false, false, 0); 71 monitor.enter(); 72 try { 73 verifyOccupiedMethodsInCurrentThread(monitor, true, true, 1); 74 verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0); 75 monitor.enter(); 76 try { 77 verifyOccupiedMethodsInCurrentThread(monitor, true, true, 2); 78 verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0); 79 } finally { 80 monitor.leave(); 81 } 82 verifyOccupiedMethodsInCurrentThread(monitor, true, true, 1); 83 verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0); 84 } finally { 85 monitor.leave(); 86 } 87 verifyOccupiedMethodsInCurrentThread(monitor, false, false, 0); 88 verifyOccupiedMethodsInAnotherThread(monitor, false, false, 0); 89 } 90 verifyOccupiedMethodsInCurrentThread( Monitor monitor, boolean expectedIsOccupied, boolean expectedIsOccupiedByCurrentThread, int expectedOccupiedDepth)91 private static void verifyOccupiedMethodsInCurrentThread( 92 Monitor monitor, 93 boolean expectedIsOccupied, 94 boolean expectedIsOccupiedByCurrentThread, 95 int expectedOccupiedDepth) { 96 assertEquals(expectedIsOccupied, monitor.isOccupied()); 97 assertEquals(expectedIsOccupiedByCurrentThread, monitor.isOccupiedByCurrentThread()); 98 assertEquals(expectedOccupiedDepth, monitor.getOccupiedDepth()); 99 } 100 verifyOccupiedMethodsInAnotherThread( final Monitor monitor, boolean expectedIsOccupied, boolean expectedIsOccupiedByCurrentThread, int expectedOccupiedDepth)101 private static void verifyOccupiedMethodsInAnotherThread( 102 final Monitor monitor, 103 boolean expectedIsOccupied, 104 boolean expectedIsOccupiedByCurrentThread, 105 int expectedOccupiedDepth) { 106 final AtomicBoolean actualIsOccupied = new AtomicBoolean(); 107 final AtomicBoolean actualIsOccupiedByCurrentThread = new AtomicBoolean(); 108 final AtomicInteger actualOccupiedDepth = new AtomicInteger(); 109 final AtomicReference<Throwable> thrown = new AtomicReference<>(); 110 joinUninterruptibly( 111 startThread( 112 new Runnable() { 113 @Override 114 public void run() { 115 try { 116 actualIsOccupied.set(monitor.isOccupied()); 117 actualIsOccupiedByCurrentThread.set(monitor.isOccupiedByCurrentThread()); 118 actualOccupiedDepth.set(monitor.getOccupiedDepth()); 119 } catch (Throwable t) { 120 thrown.set(t); 121 } 122 } 123 })); 124 assertNull(thrown.get()); 125 assertEquals(expectedIsOccupied, actualIsOccupied.get()); 126 assertEquals(expectedIsOccupiedByCurrentThread, actualIsOccupiedByCurrentThread.get()); 127 assertEquals(expectedOccupiedDepth, actualOccupiedDepth.get()); 128 } 129 } 130