/******************************************************************************* * Copyright 2014-2015 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.environment; import static org.junit.Assert.*; import java.security.SecureRandom; import java.util.UUID; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import org.eclipse.jdt.annotation.Nullable; import org.junit.Test; import com.analog.lyric.dimple.environment.DimpleEnvironment; import com.analog.lyric.dimple.environment.ExtendedLevel; import com.analog.lyric.dimple.events.DimpleEvent; import com.analog.lyric.dimple.events.DimpleEventListener; import com.analog.lyric.dimple.events.EventPrinter; import com.analog.lyric.dimple.events.IDimpleEventHandler; import com.analog.lyric.dimple.events.IDimpleEventSource; import com.analog.lyric.dimple.events.IModelEventSource; import com.analog.lyric.dimple.factorfunctions.Normal; import com.analog.lyric.dimple.model.core.FactorGraph; import com.analog.lyric.dimple.model.core.Ids; import com.analog.lyric.dimple.model.variables.Real; import com.analog.lyric.dimple.options.BPOptions; import com.analog.lyric.dimple.options.DimpleOptionHolder; import com.analog.lyric.dimple.schedulers.GibbsRandomScanScheduler; import com.analog.lyric.dimple.schedulers.validator.AllEdgeScheduleValidator; import com.analog.lyric.dimple.solvers.core.proposalKernels.NormalProposalKernel; import com.analog.lyric.dimple.solvers.gibbs.GibbsSolver; import com.analog.lyric.dimple.solvers.gibbs.samplers.generic.SliceSampler; import com.analog.lyric.dimple.test.DimpleTestBase; import com.analog.lyric.math.DimpleRandom; import com.analog.lyric.util.test.TestLogger; /** * Unit tests for {@link DimpleEnvironment} class. * @since 0.07 * @author Christopher Barber */ public class TestDimpleEnvironment extends DimpleTestBase { @SuppressWarnings("unused") @Test public void testInstances() { // Assume JUnit tests will not be run from MATLAB assertFalse(DimpleEnvironment.loadedFromMATLAB()); assertNull(DimpleEnvironment.withId(new SecureRandom().nextLong())); final DimpleEnvironment global1 = DimpleEnvironment.defaultEnvironment(); final DimpleEnvironment local1 = DimpleEnvironment.active(); assertSame(global1, local1); assertSame(global1, DimpleEnvironment.withId(global1.getEnvId())); UUID uid = global1.getUUID(); assertEquals(2, uid.variant()); assertEquals(Ids.DIMPLE_UUID_VERSION, uid.version()); assertEquals(0, uid.getLeastSignificantBits() & (1L<<62) - 1); Thread thread1 = new Thread() { @Override public void run() { assertSame(global1, DimpleEnvironment.active()); DimpleEnvironment local2 = new DimpleEnvironment(); assertNotEquals(local2.getEnvId(), global1.getEnvId()); assertSame(local2, DimpleEnvironment.withId(local2.getEnvId())); DimpleEnvironment.setActive(local2); assertSame(local2, DimpleEnvironment.active()); } }; thread1.start(); try { thread1.join(); } catch (InterruptedException ex) { fail(ex.toString()); } assertSame(local1, DimpleEnvironment.active()); final DimpleEnvironment global2 = new DimpleEnvironment(); DimpleEnvironment.setDefaultEnvironment(global2); assertSame(global2, DimpleEnvironment.defaultEnvironment()); assertSame(local1, DimpleEnvironment.active()); assertNotEquals(uid, global2.getUUID()); assertSame(local1.random(), DimpleEnvironment.activeRandom()); DimpleRandom prevRandom = local1.random(); DimpleRandom newRandom = new DimpleRandom(); assertSame(prevRandom, local1.setRandom(newRandom)); assertSame(newRandom, local1.random()); Thread thread2 = new Thread() { @Override public void run() { assertSame(global2, DimpleEnvironment.active()); DimpleEnvironment.setDefaultEnvironment(global1); assertSame(global1, DimpleEnvironment.defaultEnvironment()); assertSame(global2, DimpleEnvironment.active()); assertSame(global2.random(), DimpleEnvironment.activeRandom()); } }; thread2.start(); try { thread2.join(); } catch (InterruptedException ex) { fail(ex.toString()); } try { new DimpleEnvironment(Ids.ENV_ID_MAX + 1); } catch (IllegalArgumentException ex) { } catch (Throwable ex) { fail("expected IllegalArgumentException"); } try { new DimpleEnvironment(Ids.ENV_ID_MIN - 1); } catch (IllegalArgumentException ex) { } catch (Throwable ex) { fail("expected IllegalArgumentException"); } try { new DimpleEnvironment(DimpleEnvironment.active().getEnvId()); } catch (IllegalStateException ex) { } catch (Throwable ex) { fail("expected IllegalStateException"); } } @Test public void testEventSourceMethods() { DimpleEnvironment global = DimpleEnvironment.defaultEnvironment(); assertNull(global.getContainingGraph()); assertNull(global.getEventParent()); assertNull(global.getModelEventSource()); global.notifyListenerChanged(); // does nothing assertEquals("DimpleEnvironment", global.getEventSourceName()); class TestSource extends DimpleOptionHolder { int notifyCount = 0; @Override public @Nullable FactorGraph getContainingGraph() { return null; } @Override public @Nullable IDimpleEventSource getEventParent() { return null; } @Override public String getEventSourceName() { return "test"; } @Override public @Nullable IModelEventSource getModelEventSource() { return null; } @Override public void notifyListenerChanged() { ++notifyCount; } } TestSource source1 = new TestSource(); TestSource source2 = new TestSource(); IDimpleEventHandler<DimpleEvent> handler = new EventPrinter(); assertNull(global.getEventListener()); DimpleEventListener listener = global.createEventListener(); assertNotNull(listener); assertSame(listener, global.createEventListener()); assertSame(listener, global.getEventListener()); listener.register(handler, DimpleEvent.class, source1); global.setEventListener(null); global.setEventListener(null); assertNull(global.getEventListener()); assertEquals(1, source1.notifyCount); global.setEventListener(listener); global.setEventListener(listener); assertSame(listener, global.getEventListener()); assertEquals(2, source1.notifyCount); DimpleEventListener listener2 = new DimpleEventListener(); listener2.register(handler, DimpleEvent.class, source2); global.setEventListener(listener2); global.setEventListener(listener2); assertSame(listener2, global.getEventListener()); assertEquals(3, source1.notifyCount); assertEquals(1, source2.notifyCount); } @Test public void testLogging() { assertFalse(DimpleEnvironment.loadedFromMATLAB()); DimpleEnvironment env = DimpleEnvironment.active(); Logger defaultLogger = env.logger(); assertSame(defaultLogger, Logger.getLogger("com.analog.lyric.dimple")); assertSame(defaultLogger, DimpleEnvironment.getDefaultLogger()); TestLogger testLogger = new TestLogger("com.analog.lyric.dimple"); env.setLogger(testLogger); assertSame(testLogger, env.logger()); DimpleEnvironment.logWarning("'%s'","hi there"); LogRecord record = testLogger.loggedRecords().remove(); assertEquals(Level.WARNING, record.getLevel()); assertEquals("'hi there'", record.getMessage()); assertTrue(testLogger.loggedRecords().isEmpty()); DimpleEnvironment.logError("'%s'","whoops"); record = testLogger.loggedRecords().remove(); assertEquals(ExtendedLevel.ERROR, record.getLevel()); assertEquals("'whoops'", record.getMessage()); assertTrue(testLogger.loggedRecords().isEmpty()); DimpleEnvironment.log(Level.INFO, "info"); record = testLogger.loggedRecords().remove(); assertEquals(Level.INFO, record.getLevel()); assertEquals("info", record.getMessage()); assertTrue(testLogger.loggedRecords().isEmpty()); } @Test public void testRegistries() { DimpleEnvironment env = DimpleEnvironment.active(); assertEquals(Normal.class, env.factorFunctions().getClass("Normal")); assertSame(env.factorFunctions(), env.factorFunctions()); assertNull(env.factorGraphs().getGraphWithId(0)); assertSame(env.factorGraphs(), env.factorGraphs()); FactorGraph fg1 = new FactorGraph(); FactorGraph fg2 = new FactorGraph(); Real v1 = new Real(); fg1.addVariables(v1); assertSame(fg1, env.factorGraphs().getGraphWithId(fg1.getGraphId())); assertSame(fg2, env.factorGraphs().getGraphWithId(fg2.getGraphId())); assertSame(v1, env.getNodeByGlobalId(v1.getGlobalId())); assertNull(env.getNodeByGlobalId(0)); assertEquals(SliceSampler.class, env.genericSamplers().getClass("SliceSampler")); assertSame(env.genericSamplers(), env.genericSamplers()); assertEquals(BPOptions.iterations, env.optionRegistry().get("BPOptions.iterations")); assertSame(env.optionRegistry(), env.optionRegistry()); assertEquals(NormalProposalKernel.class, env.proposalKernels().getClass("NormalProposalKernel")); assertSame(env.proposalKernels(), env.proposalKernels()); assertEquals(GibbsSolver.class, env.solvers().getClass("Gibbs")); assertSame(env.solvers(), env.solvers()); assertEquals(GibbsRandomScanScheduler.class, env.schedulers().getClass("GibbsRandomScanScheduler")); assertSame(env.schedulers(), env.schedulers()); assertEquals(AllEdgeScheduleValidator.class, env.scheduleValidators().getClass("AllEdgeScheduleValidator")); } }