/*
* ALMA - Atacama Large Millimiter Array (c) European Southern Observatory, 2007
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package alma.acs.alarm.test.panel;
import java.util.Collection;
import java.util.Vector;
import javax.swing.SwingWorker;
import junit.framework.TestCase;
import alma.acsplugins.alarmsystem.gui.table.AlarmGUIType;
import alma.acsplugins.alarmsystem.gui.table.AlarmTableEntry;
import alma.acsplugins.alarmsystem.gui.table.AlarmsContainer;
import alma.acsplugins.alarmsystem.gui.table.AlarmsContainer.AlarmContainerException;
import alma.acsplugins.alarmsystem.gui.table.AlarmsReductionContainer;
import cern.laser.client.data.Alarm;
import alma.acs.gui.util.threadsupport.EDTExecutor;
/**
* <code>AlarmContainerTest</code> tests {@link AlarmsContainer}
* <P>
* After building an <code>AlarmsContainer</code>, the test stresses
* each of its methods in both situations i.e. with and without
* reductions.
* <P>
* Alarms container must be accessed inside the EDT because the synchronization
* is done through thread confinement. The alarm containers modify their data
* inside the EDT but reading must be done from inside the EDT.
*
* @author acaproni
*
*/
public class AlarmContainerTest extends TestCase {
/**
* MyAlarmContainer extends {@link AlarmsReductionContainer} to allow testing
* protected methods.
*
* @author acaproni
*
*/
private class MyAlarmContainer extends AlarmsReductionContainer {
/**
* Constructor
* @see AlarmsReductionContainer#AlarmsReductionContainer(int)
*/
public MyAlarmContainer(int max) {
super(max);
}
/**
* @see AlarmsContainer#removeInactiveAlarms(AlarmGUIType type)
*/
@Override
public int removeInactiveAlarms(AlarmGUIType type)
throws AlarmContainerException {
return super.removeInactiveAlarms(type);
}
}
/**
* The max number of alarms in the container
*/
private final int CONTAINER_SIZE = 10000;
/**
* The container to test
*/
private MyAlarmContainer container;
/**
* Constructor
*
* @throws Exception
*/
public AlarmContainerTest() throws Exception {
super(AlarmContainerTest.class.getName());
}
/**
* @see alma.acs.component.client.ComponentClientTestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
TestAlarm.alarm_generator_id=0;
container = new MyAlarmContainer(CONTAINER_SIZE);
assertNotNull(container);
}
/**
* @see alma.acs.component.client.ComponentClientTestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception {
container.clear();
super.tearDown();
}
/**
* Check the size of the container
*
* @throws Exception
*/
public void testContainerSize() throws Exception {
// Check the size of the empty container
EDTExecutor.instance().executeSync(new Runnable() {
@Override
public void run() {
assertEquals(0,container.size(false));
assertEquals(0,container.size(true));
}
});
// Add half of the max number of alarms
int notReduced=populateContainer(CONTAINER_SIZE/2, "TEST",null,null);
class EDTReader implements Runnable {
// The value to check after reading from EDT
private final int value;
EDTReader(int val) {
value=val;
}
public void run() {
assertEquals("Wrong not reduced size",CONTAINER_SIZE/2, container.size(false));
assertEquals("Wrong reduced size",value, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader(notReduced));
// Add the other alarms until the container is full
notReduced+=populateContainer(CONTAINER_SIZE/2, "TEST", null,null);
class EDTReader2 implements Runnable {
// The value to check after reading from EDT
private final int value;
EDTReader2(int val) {
value=val;
}
public void run() {
assertEquals("Wrong not reduced size",CONTAINER_SIZE, container.size(false));
assertEquals("Wrong reduced size",value, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader2(notReduced));
// Adding one more item, an exception should be thrown
boolean exceptionThrown=false;
try {
container.add(new AlarmTableEntry(TestAlarm.generateRndAlarm("TEST")));
} catch (Exception e) {
exceptionThrown=true;
}
assertTrue(exceptionThrown);
// Finally clear the container
EDTExecutor.instance().executeSync(new Runnable() {
@Override
public void run() {
container.clear();
assertEquals(0,container.size(false));
assertEquals(0,container.size(true));
}
});
}
/**
* Test the removal of alarms
*
* @throws Exception
*/
public void testAlarmsRemove() throws Exception {
// Add some alarms
int notReduced=0;
Vector<Alarm> alarms = new Vector<Alarm>();
notReduced = populateContainer(CONTAINER_SIZE/2, "TEST", alarms,null);
class EDTReader implements Runnable {
// The value to check after reading from EDT
private final int value;
EDTReader(int val) {
value=val;
}
public void run() {
assertEquals("Wrong not reduced size",CONTAINER_SIZE/2, container.size(false));
assertEquals("Wrong reduced size",value, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader(notReduced));
// Trying to remove an alarm not in the container throws an exception
Alarm al = TestAlarm.generateRndAlarm("EXCEPTION");
boolean exceptionOccurred=false;
try {
container.remove(new AlarmTableEntry(al));
} catch (AlarmContainerException e) {
exceptionOccurred=true;
}
assertTrue(exceptionOccurred);
// Remove all the alarms checking the number of alarms in the container
int sz = CONTAINER_SIZE/2;
int reducedToRemove=notReduced;
for (Alarm removedAlarm: alarms) {
container.remove(new AlarmTableEntry(removedAlarm));
sz--;
if (!removedAlarm.getStatus().isReduced()) {
reducedToRemove--;
}
class EDTReader2 implements Runnable {
// The values to check after reading from EDT
private final int sz;
private final int reducedToRemove;
EDTReader2(int sz,int reducedToRemove) {
this.sz=sz;
this.reducedToRemove=reducedToRemove;
}
public void run() {
assertEquals(sz, container.size(false));
assertEquals(reducedToRemove, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader2(sz,reducedToRemove));
}
// The container is empty
EDTExecutor.instance().executeSync(new Runnable() {
@Override
public void run() {
assertEquals(0,container.size(false));
assertEquals(0,container.size(true));
}
});
}
/**
* Populate the container with the passed number of randomly generated alarms.
*
* @param size The number of alarms to add to the container
* @param fm The fault family of the added alarms
* @param generatedAlarms A <code>Collection</code> containing the generated alarms;
* it can be <code>null</code>; if it is not null, the newly generated
* alarms are added to the collection.
* @param entries The <code>AlarmtableEntry</code> generated while adding alarms to the container
* it can be <code>null</code>; if it is not <code>null</code>, the newly generated
* entries are added to the collection.
*
* @return The number of not reduced alarms in the collection
*/
private int populateContainer(
int size,
String fm,
Collection<Alarm> generatedAlarms,
Collection<AlarmTableEntry> entries) throws Exception {
int notReduced=0;
int originalCollectionAlarmsSize=0;
if (generatedAlarms!=null) {
originalCollectionAlarmsSize=generatedAlarms.size();
}
int originalCollectionEntriesSize=0;
if (entries!=null) {
originalCollectionEntriesSize=entries.size();
}
for (int t=0; t<size; t++) {
Alarm alarm = TestAlarm.generateRndAlarm(fm);
if (generatedAlarms!=null) {
generatedAlarms.add(alarm);
}
if (!alarm.getStatus().isReduced()) {
notReduced++;
}
container.add(new AlarmTableEntry(alarm));
}
if (generatedAlarms!=null) {
assertEquals(size, generatedAlarms.size()-originalCollectionAlarmsSize);
}
if (entries!=null) {
assertEquals(size, entries.size()-originalCollectionEntriesSize);
}
return notReduced;
}
/**
* Test <code>removeOldest()</code>
*
* @throws Exception
*/
public void testRemoveOldest() throws Exception {
// Add some alarms
final Vector<Alarm> alarms = new Vector<Alarm>();
int notReduced = populateContainer(CONTAINER_SIZE/2, "TEST", alarms,null);
class EDTReader implements Runnable {
// The value to check after reading from EDT
private final int value;
EDTReader(int val) {
value=val;
}
public void run() {
assertEquals("Wrong not reduced size",CONTAINER_SIZE/2, container.size(false));
assertEquals("Wrong reduced size",value, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader(notReduced));
final AlarmTableEntry removedEntry = container.removeOldest();
assertNotNull(removedEntry);
// Check the sizes
class EDTReader2 implements Runnable {
// The value to check after reading from EDT
private final int notReduced;
EDTReader2(int notReduced) {
this.notReduced=notReduced;
}
public void run() {
assertEquals(alarms.size()-1, container.size(false));
if (removedEntry.isReduced()) {
assertEquals(notReduced, container.size(true));
} else {
assertEquals(notReduced-1, container.size(true));
}
}
}
EDTExecutor.instance().executeSync(new EDTReader2(notReduced));
// Check if removed alarms was the oldest alarm
assertEquals(alarms.get(0).getAlarmId(), removedEntry.getAlarmId());
}
/**
* Test <code>replaceAlarm()</code>
*
* @throws Exception
*/
public void testReplaceAlarm() throws Exception {
// Add some alarms
Vector<Alarm> alarms = new Vector<Alarm>();
int notReduced = populateContainer(CONTAINER_SIZE/2, "TEST", alarms,null);
class EDTReader implements Runnable {
// The value to check after reading from EDT
private final int value;
EDTReader(int val) {
value=val;
}
public void run() {
assertEquals("Wrong not reduced size",CONTAINER_SIZE/2, container.size(false));
assertEquals("Wrong reduced size",value, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader(notReduced));
// replace the first alarm with another one changing the
// active attribute
Alarm alarmToReplace = alarms.get(0);
assertNotNull(alarmToReplace);
Alarm newAlarm = new TestAlarm(
alarmToReplace.getAlarmId(),
alarmToReplace.isNodeChild(),
alarmToReplace.isNodeParent(),
!alarmToReplace.getStatus().isActive(),
alarmToReplace.getStatus().isMasked(),
alarmToReplace.getStatus().isReduced());
class ReplaceAndCheck implements Runnable {
private final Alarm newAlarm;
ReplaceAndCheck(Alarm newAlarm) {
this.newAlarm=newAlarm;
}
public void run() {
try {
container.replace(new AlarmTableEntry(newAlarm));
} catch (Throwable t) {
System.err.println("Error replacing alarm "+newAlarm.getAlarmId());
t.printStackTrace();
}
AlarmTableEntry entry = container.get(newAlarm.getAlarmId());
assertEquals(newAlarm.getAlarmId(), entry.getAlarmId());
assertEquals(newAlarm.getStatus().isActive(), entry.getStatus().isActive());
}
}
EDTExecutor.instance().executeSync(new ReplaceAndCheck(newAlarm));
// replace the LAST alarm with another one changing the
// active attribute
alarmToReplace = alarms.get(alarms.size()-1);
assertNotNull(alarmToReplace);
newAlarm = new TestAlarm(
alarmToReplace.getAlarmId(),
alarmToReplace.isNodeChild(),
alarmToReplace.isNodeParent(),
!alarmToReplace.getStatus().isActive(),
alarmToReplace.getStatus().isMasked(),
alarmToReplace.getStatus().isReduced());
EDTExecutor.instance().executeSync(new ReplaceAndCheck(newAlarm));
// replace a middle-list alarm with another one changing the
// active attribute
alarmToReplace = alarms.get(alarms.size()/2);
assertNotNull(alarmToReplace);
newAlarm = new TestAlarm(
alarmToReplace.getAlarmId(),
alarmToReplace.isNodeChild(),
alarmToReplace.isNodeParent(),
!alarmToReplace.getStatus().isActive(),
alarmToReplace.getStatus().isMasked(),
alarmToReplace.getStatus().isReduced());
EDTExecutor.instance().executeSync(new ReplaceAndCheck(newAlarm));
}
/**
* Test the removal of inactive alarms
*
* @throws Exception
*/
public void testRemoveInactivAls() throws Exception {
final Vector<Alarm> alarms= new Vector<Alarm>();
int notReduced;
// Stores for each priority the number of inactive alarms
final int[] priorities =new int[AlarmGUIType.values().length-1];
// The test is done for each AlarmGUIType corresponding to a priority
for (AlarmGUIType alarmType: AlarmGUIType.values()) {
// Add some alarms
alarms.clear();
assertEquals(0, alarms.size());
EDTExecutor.instance().executeSync(new Runnable() {
@Override
public void run() {
container.clear();
assertEquals(0, container.size(false));
}
});
for (int t=0; t<4; t++) {
priorities[t]=0;
}
notReduced = populateContainer(CONTAINER_SIZE/2, "TEST", alarms,null);
class EDTReader implements Runnable {
// The value to check after reading from EDT
private final int value;
EDTReader(int val) {
value=val;
}
public void run() {
assertEquals("Wrong not reduced size",CONTAINER_SIZE/2, container.size(false));
assertEquals("Wrong reduced size",value, container.size(true));
}
}
EDTExecutor.instance().executeSync(new EDTReader(notReduced));
for (Alarm al: alarms) {
if (!al.getStatus().isActive()) {
priorities[al.getPriority()]++;
}
}
class Checker implements Runnable {
private final AlarmGUIType alarmType;
public Checker(AlarmGUIType alarmType) {
this.alarmType=alarmType;
}
public void run() {
try {
container.removeInactiveAlarms(alarmType);
} catch (Throwable t) {
System.out.println("Error removing inactive alarms for "+alarmType);
t.printStackTrace();
return;
}
if (alarmType!=AlarmGUIType.INACTIVE) {
assertEquals(alarms.size()-priorities[alarmType.ordinal()], container.size(false));
} else {
int newSize = alarms.size()-priorities[0]-priorities[1]-priorities[2]-priorities[3];
assertEquals(newSize, container.size(false));
}
}
}
EDTExecutor.instance().executeSync(new Checker(alarmType));
}
}
}