/* $HeadURL$
* $Id$
*
* Copyright (c) 2009-2010 DuraSpace
* http://duraspace.org
*
* In collaboration with Topaz Inc.
* http://www.topazproject.org
*
* 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.
*/
package org.akubraproject.qsc;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import org.testng.annotations.Test;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* Unit Tests for {@link QuiescingStreamManager}.
*
* @author Chris Wilper
*/
public class TestQuiescingStreamManager {
private final QuiescingStreamManager manager = new QuiescingStreamManager();
/**
* Manager should start in the unquiescent state with no tracked streams.
*/
@Test(groups={ "init" })
public void testInitialState() {
assertFalse(manager.isQuiescent());
}
/**
* Setting quiescent state should be respected and setting to the current
* value should have no effect.
*/
@Test(dependsOnGroups = { "init" })
public void testSetQuiescentWhileInactive() throws Exception {
manager.setQuiescent(true);
assertTrue(manager.isQuiescent());
manager.setQuiescent(true);
assertTrue(manager.isQuiescent());
manager.setQuiescent(false);
assertFalse(manager.isQuiescent());
manager.setQuiescent(false);
assertFalse(manager.isQuiescent());
}
/**
* Going into quiescent state while an OutputStream is open should block,
* then return true when the stream is closed.
*/
@Test(dependsOnGroups = { "init" })
public void testGoQuiescentOpenStreamBlocking() throws Exception {
OutputStream managed = null;
manager.lockUnquiesced();
try {
managed = manager.manageOutputStream(null, new ByteArrayOutputStream());
} finally {
manager.unlockState();
}
GoQuiescentThread thread = new GoQuiescentThread(manager);
thread.start();
Thread.sleep(100);
assertTrue(thread.isAlive()); // thread should be blocking
managed.close();
thread.join(); // thread will now terminate; wait for it
assertTrue(thread.getReturnValue());
assertNull(thread.getException());
assertTrue(manager.setQuiescent(false));
}
/**
* Going into quiescent state while an OutputStream is open should block,
* then return false if interrupted.
*/
@Test(dependsOnGroups = { "init" })
public void testGoQuiescentOpenStreamInterrupted() throws Exception {
OutputStream managed = null;
manager.lockUnquiesced();
try {
managed = manager.manageOutputStream(null, new ByteArrayOutputStream());
} finally {
manager.unlockState();
}
GoQuiescentThread thread = new GoQuiescentThread(manager);
thread.start();
Thread.sleep(100);
assertTrue(thread.isAlive()); // thread should be blocking
thread.interrupt();
thread.join(); // thread will now terminate; wait for it
assertFalse(thread.getReturnValue());
assertNull(thread.getException());
managed.close();
assertTrue(manager.setQuiescent(false));
}
/**
* Going into quiescent state while the state lock is held should block,
* then return true when the state lock is released.
*/
@Test(dependsOnGroups = { "init" })
public void testGoQuiescentStateLockBlocking() throws Exception {
GoQuiescentThread thread = new GoQuiescentThread(manager);
manager.lockUnquiesced();
try {
thread.start();
Thread.sleep(100);
assertTrue(thread.isAlive()); // thread should be blocking
} finally {
manager.unlockState();
}
thread.join(); // thread will now terminate; wait for it
assertTrue(thread.getReturnValue());
assertNull(thread.getException());
assertTrue(manager.setQuiescent(false));
}
/**
* Going into quiescent state while the state lock is held should block,
* then return false if interrupted.
*/
@Test(dependsOnGroups = { "init" })
public void testGoQuiescentStateLockInterrupted() throws Exception {
manager.lockUnquiesced();
try {
GoQuiescentThread thread = new GoQuiescentThread(manager);
thread.start();
Thread.sleep(100);
assertTrue(thread.isAlive()); // thread should be blocking
thread.interrupt();
thread.join(); // thread will now terminate; wait for it
assertFalse(thread.getReturnValue());
assertNull(thread.getException());
} finally {
manager.unlockState();
}
assertTrue(manager.setQuiescent(false));
}
/**
* Attempting to lock unquiesced should block and return true when the
* unquiescent state is reached.
*/
@Test(dependsOnGroups = { "init" })
public void testGoUnquiescentBlocking() throws Exception {
assertTrue(manager.setQuiescent(true));
LockUnquiescedThread thread = new LockUnquiescedThread(manager);
thread.start();
Thread.sleep(100);
assertTrue(thread.isAlive()); // thread should be blocking
assertTrue(manager.setQuiescent(false));
thread.join(); // thread will now terminate; wait for it
assertNull(thread.getException());
}
/**
* Attempting to lock unquiesced should block and return false if interrupted.
*/
@Test(dependsOnGroups = { "init" })
public void testGoUnquiescentInterrupted() throws Exception {
assertTrue(manager.setQuiescent(true));
LockUnquiescedThread thread = new LockUnquiescedThread(manager);
thread.start();
Thread.sleep(100);
assertTrue(thread.isAlive()); // thread should be blocking
thread.interrupt();
thread.join(); // thread will now terminate; wait for it
assertNotNull(thread.getException());
assertTrue(manager.setQuiescent(false));
}
private static class GoQuiescentThread extends Thread {
private final QuiescingStreamManager manager;
private boolean returnValue;
private Throwable t;
public GoQuiescentThread(QuiescingStreamManager manager) {
this.manager = manager;
}
@Override
public void run() {
try {
returnValue = manager.setQuiescent(true);
} catch (Throwable t) {
this.t = t;
}
}
public boolean getReturnValue() {
return returnValue;
}
public Throwable getException() {
return t;
}
}
private static class LockUnquiescedThread extends Thread {
private final QuiescingStreamManager manager;
private Throwable t;
public LockUnquiescedThread(QuiescingStreamManager manager) {
this.manager = manager;
}
@Override
public void run() {
try {
manager.lockUnquiesced();
manager.unlockState();
} catch (Throwable t) {
this.t = t;
}
}
public Throwable getException() {
return t;
}
}
}