/*******************************************************************************
* Copyright 2014 Analog Devices, Inc.
*
* 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 com.analog.lyric.dimple.test.events;
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.List;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.Test;
import com.analog.lyric.dimple.environment.DimpleEnvironment;
import com.analog.lyric.dimple.events.DimpleEvent;
import com.analog.lyric.dimple.events.DimpleEventListener;
import com.analog.lyric.dimple.events.DimpleEventLogger;
import com.analog.lyric.dimple.events.IDimpleEventSource;
import com.analog.lyric.dimple.events.IModelEventSource;
import com.analog.lyric.dimple.model.core.FactorAddEvent;
import com.analog.lyric.dimple.model.core.FactorGraph;
import com.analog.lyric.dimple.model.domains.DiscreteDomain;
import com.analog.lyric.dimple.model.variables.Discrete;
import com.analog.lyric.dimple.test.DimpleTestBase;
import com.google.common.io.Files;
/**
* Unit test for {@link DimpleEventLogger}
*
* @since 0.06
* @author Christopher Barber
*/
@SuppressWarnings({"null", "deprecation"})
public class TestDimpleEventLogger extends DimpleTestBase
{
@Test
public void test() throws IOException
{
final DimpleEnvironment env = DimpleEnvironment.active();
assertNull(env.getEventListener());
DimpleEventLogger logger = new DimpleEventLogger();
assertTrue(logger.isClear());
assertSame(System.err, logger.out());
assertEquals(0, logger.verbosity());
assertNull(logger.file());
assertTrue(logger.isOpen());
assertSame(env, logger.getEnvironment());
logger.close();
assertFalse(logger.isOpen());
assertNull(logger.out());
logger.clear();
logger.open(System.out);
assertTrue(logger.isOpen());
assertSame(System.out, logger.out());
File tmpFile = null;
try
{
tmpFile = File.createTempFile("TestDimpleEventLogger", ".txt");
tmpFile.deleteOnExit();
logger.open(tmpFile);
assertTrue(logger.isOpen());
assertSame(tmpFile, logger.file());
logger.out().println("test");
assertFile(tmpFile, "test");
logger.close();
assertFalse(logger.isOpen());
logger.open(tmpFile);
logger.out().println("foo");
assertFile(tmpFile, "test", "foo");
logger.open(tmpFile, false);
logger.out().println("barf");
assertFile(tmpFile, "barf");
}
finally
{
logger.close();
if (tmpFile != null)
{
assertTrue(tmpFile.delete());
}
}
// Force line separator character used by PrintStream to be \n to avoid problems on Windows.
System.setProperty("line.separator", "\n");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bos);
logger.open(out);
assertTrue(logger.isOpen());
assertSame(out, logger.out());
assertNull(logger.file());
assertTrue(logger.logEntries().isEmpty());
FactorGraph fg = new FactorGraph();
assertNull(fg.getEventListener());
Discrete d = new Discrete(DiscreteDomain.bit());
fg.addVariables(d);
assertTrue(logger.isClear());
logger.log(TestEvent.class); // no effect
assertTrue(logger.isClear());
logger.log(TestEvent.class, fg);
assertFalse(logger.isClear());
DimpleEventListener listener = env.getEventListener();
assertSame(listener, fg.getEventListener());
listener.raiseEvent(new TestEvent(fg));
List<DimpleEventLogger.LogEntry> entries = logger.logEntries();
assertEquals(1, entries.size());
assertEquals(fg, entries.get(0).eventSource());
assertEquals(TestEvent.class, entries.get(0).eventClass());
assertEquals("verbosity=0\n", bos.toString());
bos.reset();
logger.verbosity(1);
assertEquals(1, logger.verbosity());
listener.raiseEvent(new TestEvent(fg));
assertEquals("TestEvent: verbosity=1\n", bos.toString());
bos.reset();
logger.close();
assertTrue(fg.getEventListener().isListeningFor(TestEvent.class, fg));
listener.raiseEvent(new TestEvent(fg));
assertEquals("", bos.toString());
bos.reset();
logger.clear();
assertTrue(logger.logEntries().isEmpty());
assertTrue(logger.isClear());
assertNull(fg.getEventListener());
assertFalse(listener.isListeningFor(TestEvent.class, fg));
// Make sure that logger will not replace an existing listener with the default listener
listener = new DimpleEventListener();
listener.block(FactorAddEvent.class, true, fg);
fg.setEventListener(listener);
logger.log(TestEvent.class, fg);
assertTrue(listener.isListeningFor(TestEvent.class, fg));
assertSame(listener, fg.getEventListener());
assertFalse(listener.isDefault());
entries = logger.logEntries();
assertEquals(1, entries.size());
assertSame(TestEvent.class, entries.get(0).eventClass());
logger.open(out = new PrintStream(bos));
listener.raiseEvent(new TestEvent(fg));
assertEquals("TestEvent: verbosity=1\n", bos.toString());
bos.reset();
assertEquals(0, logger.unlog(TestEvent.class, d));
assertEquals(0, logger.unlog(DimpleEvent.class, fg));
assertEquals(1, logger.unlog(TestEvent.class, fg));
assertEquals(0, logger.logEntries().size());
logger.log(TestEvent.class, d);
logger.log(TestEvent.class, fg);
assertEquals(2, logger.logEntries().size());
logger.clear();
assertEquals(0, logger.logEntries().size());
assertSame(listener, fg.getEventListener());
logger.log(TestEvent.class, d);
assertTrue(listener.isListeningFor(TestEvent.class, d));
fg.setEventListener(null);
assertTrue(listener.isListeningFor(TestEvent.class, d));
// No entry removed because listener has changed.
assertEquals(0, logger.unlog(TestEvent.class, d));
assertEquals(1, logger.logEntries().size());
logger.clear();
}
private static class TestEvent extends DimpleEvent
{
private static final long serialVersionUID = 1L;
TestEvent(IDimpleEventSource source)
{
super(source);
}
@Override
protected void printDetails(PrintStream out, int verbosity)
{
out.format("verbosity=%d", verbosity);
}
@Override
public @Nullable IModelEventSource getModelObject()
{
IDimpleEventSource src = getSource();
return src != null ? src.getModelEventSource() : null;
}
}
private void assertFile(File file, String ... expectedLines) throws IOException
{
List<String> actualLines = Files.readLines(file, Charset.defaultCharset());
assertArrayEquals(expectedLines, actualLines.toArray());
}
}