/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.datasource.test;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executor;
import org.diirt.datasource.DataSource;
import static org.diirt.datasource.ExpressionLanguage.*;
import org.diirt.datasource.PV;
import org.diirt.datasource.PVManager;
import org.diirt.datasource.PVReader;
import org.diirt.datasource.PVWriter;
import org.diirt.datasource.PVWriterEvent;
import org.diirt.util.concurrent.Executors;
import static java.time.Duration.*;
import org.diirt.util.time.TimeInterval;
import static org.hamcrest.Matchers.*;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author carcassi
*/
public class PVWriterFullTest {
public PVWriterFullTest() {
}
public static void waitForChannelToClose(DataSource source, String channelName) {
Duration timeout = ofMillis(5000);
TimeInterval timeoutInterval = TimeInterval.after(timeout, Instant.now());
while (timeoutInterval.contains(Instant.now())) {
if (source.getChannels().get(channelName) == null || !source.getChannels().get(channelName).isConnected()) {
return;
}
try {
Thread.sleep(100);
} catch(Exception ex) {
}
}
fail("Channel " + channelName + " didn't close after 5 seconds");
}
private DataSource dataSource;
private Executor executor = java.util.concurrent.Executors.newSingleThreadExecutor(Executors.namedPool("PVWriterFullTest "));
PV<Object, Object> pv;
PVReader<Object> pvReader;
PVReader<Object> pvReader2;
PVWriter<Object> pvWriter;
@Before
public void setupDataSource() throws Exception {
dataSource = new TestDataSource();
}
@After
public void closePVsAndDataSource() {
if (pv != null) {
pv.close();
pv = null;
}
if (pvReader != null) {
pvReader.close();
pvReader = null;
}
if (pvReader2 != null) {
pvReader2.close();
pvReader2 = null;
}
if (pvWriter != null) {
pvWriter.close();
pvWriter = null;
}
waitForChannelToClose(dataSource, "delayedWrite");
waitForChannelToClose(dataSource, "BrokenWrite");
waitForChannelToClose(dataSource, "normal");
waitForChannelToClose(dataSource, "delayedConnection");
dataSource.close();
dataSource = null;
}
@Test
public void writerConnected() throws Exception {
CountDownPVWriterListener<Object> listener = new CountDownPVWriterListener<>(1);
pvWriter = PVManager.write(channel("normal"))
.writeListener(listener)
.notifyOn(executor)
.from(dataSource)
.async();
// Wait for the connection notification
listener.await(Duration.ofMillis(200));
assertThat(listener.getCount(), equalTo(0));
assertThat(listener.getEvent().getNotificationMask(), equalTo(PVWriterEvent.CONNECTION_MASK));
assertThat(listener.getThreadName(), equalTo("PVWriterFullTest 1"));
assertThat(pvWriter.lastWriteException(), equalTo(null));
assertThat(pvWriter.isWriteConnected(), equalTo(true));
assertThat(listener.getNotificationCount(), equalTo(1));
}
@Test
public void writerWriteSuccessful() throws Exception {
CountDownPVWriterListener<Object> listener = new CountDownPVWriterListener<>(1);
pvWriter = PVManager.write(channel("normal"))
.writeListener(listener)
.notifyOn(executor)
.from(dataSource)
.async();
// Wait for the connection notification
listener.await(Duration.ofMillis(200));
assertThat(listener.getCount(), equalTo(0));
listener.resetCount(1);
pvWriter.write("Value");
listener.await(Duration.ofMillis(200));
assertThat(listener.getCount(), equalTo(0));
assertThat(listener.getEvent().getNotificationMask(), equalTo(PVWriterEvent.WRITE_SUCCEEDED_MASK));
assertThat(listener.getThreadName(), equalTo("PVWriterFullTest 1"));
assertThat(pvWriter.lastWriteException(), equalTo(null));
assertThat(pvWriter.isWriteConnected(), equalTo(true));
assertThat(listener.getNotificationCount(), equalTo(2));
}
@Test
public void writerWriteFailed() throws Exception {
CountDownPVWriterListener<Object> listener = new CountDownPVWriterListener<>(1);
pvWriter = PVManager.write(channel("normal"))
.writeListener(listener)
.notifyOn(executor)
.from(dataSource)
.async();
// Wait for the connection notification
listener.await(Duration.ofMillis(200));
assertThat(listener.getCount(), equalTo(0));
listener.resetCount(1);
pvWriter.write("Fail");
listener.await(Duration.ofMillis(400));
assertThat(listener.getCount(), equalTo(0));
assertThat(listener.getEvent().getNotificationMask(), equalTo(PVWriterEvent.WRITE_FAILED_MASK));
assertThat(listener.getThreadName(), equalTo("PVWriterFullTest 1"));
Exception ex = pvWriter.lastWriteException();
assertThat(ex, not(equalTo(null)));
assertThat(ex.getMessage(), equalTo("Total failure"));
assertThat(pvWriter.isWriteConnected(), equalTo(true));
assertThat(listener.getNotificationCount(), equalTo(2));
}
@Test
public void writerSyncWriteSuccessful() throws Exception {
CountDownPVWriterListener<Object> listener = new CountDownPVWriterListener<>(1);
pvWriter = PVManager.write(channel("normal"))
.writeListener(listener)
.notifyOn(executor)
.from(dataSource)
.sync();
// Wait for the connection notification
listener.await(Duration.ofMillis(200));
assertThat(listener.getCount(), equalTo(0));
pvWriter.write("Value");
assertThat(listener.getEvent().getNotificationMask(), equalTo(PVWriterEvent.WRITE_SUCCEEDED_MASK));
assertThat(listener.getThreadName(), equalTo("PVWriterFullTest 1"));
assertThat(pvWriter.lastWriteException(), equalTo(null));
assertThat(pvWriter.isWriteConnected(), equalTo(true));
assertThat(listener.getNotificationCount(), equalTo(2));
}
@Test
public void writerSyncWriteFailed() throws Exception {
CountDownPVWriterListener<Object> listener = new CountDownPVWriterListener<>(1);
pvWriter = PVManager.write(channel("normal"))
.writeListener(listener)
.notifyOn(executor)
.from(dataSource)
.sync();
// Wait for the connection notification
listener.await(Duration.ofMillis(200));
assertThat(listener.getCount(), equalTo(0));
Throwable cause = null;
try {
pvWriter.write("Fail");
} catch(Exception ex) {
assertThat(ex, instanceOf(RuntimeException.class));
assertThat(ex.getMessage(), equalTo("Write failed"));
cause = ex.getCause();
}
assertThat(listener.getEvent().getNotificationMask(), equalTo(PVWriterEvent.WRITE_FAILED_MASK));
assertThat(listener.getThreadName(), equalTo("PVWriterFullTest 1"));
Exception ex = pvWriter.lastWriteException();
assertThat(ex, not(equalTo(null)));
assertThat(ex.getMessage(), equalTo("Total failure"));
assertThat(ex, sameInstance(cause));
assertThat(pvWriter.isWriteConnected(), equalTo(true));
assertThat(listener.getNotificationCount(), equalTo(2));
}
@Test
public void writerConnectionTimeout() {
// create writer with timeout and delayed connection
// wait for notification
// check elapsed time
// check notification type (correct exception)
// check thread for notification
// check writer state
// wait for second notification
// check notification type (connection)
// check thread for notification
// check writer state
}
}