/******************************************************************************* * Copyright 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.data; import static com.analog.lyric.dimple.model.sugar.ModelSyntacticSugar.*; import static com.analog.lyric.util.test.ExceptionTester.*; import static org.junit.Assert.*; import java.util.AbstractMap; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import org.junit.Test; import com.analog.lyric.collect.PrimitiveIterator; import com.analog.lyric.dimple.data.DataDensity; import com.analog.lyric.dimple.data.DataEntry; import com.analog.lyric.dimple.data.DataLayer; import com.analog.lyric.dimple.data.DataLayerBase; import com.analog.lyric.dimple.data.DenseFactorGraphData; import com.analog.lyric.dimple.data.FactorGraphData; import com.analog.lyric.dimple.data.IDatum; import com.analog.lyric.dimple.data.SparseFactorGraphData; import com.analog.lyric.dimple.model.core.FactorGraph; import com.analog.lyric.dimple.model.core.IFactorGraphChild; import com.analog.lyric.dimple.model.core.Ids; import com.analog.lyric.dimple.model.sugar.ModelSyntacticSugar.CurrentModel; import com.analog.lyric.dimple.model.values.RealValue; import com.analog.lyric.dimple.model.variables.Bit; import com.analog.lyric.dimple.model.variables.Real; import com.analog.lyric.dimple.model.variables.Variable; import com.analog.lyric.dimple.test.DimpleTestBase; import com.google.common.collect.Iterables; /** * Unit tests for {@link FactorGraphData} classes. * * @since 0.08 * @author Christopher Barber */ public class TestFactorGraphData extends DimpleTestBase { @Test public void test() { test(DenseFactorGraphData.constructorForType(Variable.class, IDatum.class)); test(SparseFactorGraphData.constructorForType(Variable.class, IDatum.class)); } public <D extends IDatum> void test(FactorGraphData.Constructor<Variable,D> dataConstructor) { Class<D> type = dataConstructor.baseType(); FactorGraph root = new FactorGraph("root"); try (CurrentModel cur = using(root)) { Real[] r = reals("r", 100); DataLayerBase<Variable,D> layer = new DataLayer<>(root, dataConstructor); FactorGraphData<Variable,D> data = dataConstructor.apply(layer, root); assertInvariants(data); assertEquals(0, data.size()); data.put(r[3], type.cast(RealValue.create(1.23))); data.put(r[78], type.cast(RealValue.create(4.5))); assertInvariants(data); assertEquals(2, data.size()); data.entrySet().add(new AbstractMap.SimpleEntry<Variable,D>(r[23], type.cast(RealValue.create(1.0)))); assertInvariants(data); assertFalse(data.containsLocalIndex(Ids.indexFromLocalId(r[4].getLocalId()))); Map<Variable,D> copy = new HashMap<>(data); data.clear(); assertInvariants(data); assertTrue(data.isEmpty()); data.putAll(copy); assertInvariants(data); assertEquals(3, data.size()); data.entrySet().clear(); assertInvariants(data); assertTrue(data.isEmpty()); data.putAll(copy); assertInvariants(data); assertEquals(3, data.size()); data.keySet().clear(); assertInvariants(data); assertEquals(0, data.size()); data.putAll(copy); assertInvariants(data); assertEquals(3, data.size()); assertNull(data.remove(r[2])); assertSame(data.get(r[3]), data.remove(r[3])); assertNull(data.get(r[3])); assertInvariants(data); assertEquals(2, data.size()); assertTrue(data.keySet().remove(r[78])); assertFalse(data.keySet().remove(r[78])); assertEquals(1, data.size()); data.putAll(copy); assertInvariants(data); assertEquals(3, data.size()); assertTrue(data.entrySet().remove(new AbstractMap.SimpleEntry<>(r[78], data.get(r[78])))); assertEquals(2, data.size()); expectThrow(IllegalArgumentException.class, data, "put", new Bit(), RealValue.create()); } } public static <K extends IFactorGraphChild, D extends IDatum> void assertInvariants(FactorGraphData<K,D> data) { class DL<D2 extends IDatum> extends DataLayerBase<K,D2> { protected DL(FactorGraph graph, DataDensity density, Class<K> keyType, Class<D2> baseType) { super(graph, density, keyType, baseType); } public DL(FactorGraph graph, FactorGraphData.Constructor<K,D2> constructor) { super(graph, constructor); } private DL(DL<D2> other) { super(other); } @Override public DataLayerBase<K, D2> clone() { return new DL<>(this); } } final FactorGraph graph = data.graph(); assertTrue(data.layer().sharesRoot(graph)); final Class<K> keyType = data.keyType(); assertTrue(IFactorGraphChild.class.isAssignableFrom(keyType)); final Class<D> baseType = data.baseType(); assertTrue(IDatum.class.isAssignableFrom(baseType)); assertTrue(data.objectEquals(data)); assertFalse(data.objectEquals(null)); assertFalse(data.objectEquals("bogus")); FactorGraph otherGraph = new FactorGraph(); DataLayerBase<K,IDatum> otherLayer = new DL<>(otherGraph, DataDensity.SPARSE, keyType, IDatum.class); assertFalse(data.objectEquals(otherLayer.createDataForGraph(otherGraph))); assertFalse(data.containsKey("not a variable")); assertFalse(data.containsLocalIndex(-1)); assertNull(data.get((Object)null)); assertNull(data.get("not a variable")); assertNull(data.get(new Real())); assertNull(data.remove("not a variable")); assertNull(data.remove(new Real())); final int size = data.size(); final Set<K> keys = data.keySet(); final Set<Map.Entry<K,D>> entries = data.entrySet(); final Collection<? extends DataEntry<K,D>> entries2 = data.entries(); final Collection<D> values = data.values(); assertEquals(size, keys.size()); assertEquals(size, entries.size()); assertEquals(size, entries2.size()); assertEquals(size, values.size()); assertEquals(size == 0, data.isEmpty()); assertFalse(keys.contains("not a variable")); assertFalse(keys.remove("not a variable")); assertFalse(entries.contains("not an entry")); assertFalse(entries.remove("not an entry")); PrimitiveIterator.OfInt indexIter = data.getLocalIndices().iterator(); PrimitiveIterator.OfInt indexIter2 = data.getLocalIndices().iterator(); Iterator<K> keyIter = keys.iterator(); Iterator<D> valueIter = values.iterator(); Iterator<Map.Entry<K,D>> entryIter = entries.iterator(); Iterator<? extends DataEntry<K,D>> entryIter2 = entries2.iterator(); int count = 0; while (entryIter.hasNext()) { ++count; assertTrue(keyIter.hasNext()); assertTrue(valueIter.hasNext()); assertTrue(entryIter2.hasNext()); Map.Entry<K,D> entry = entryIter.next(); DataEntry<K,D> entry2 = entryIter2.next(); assertEquals(entry2, entry); K key = entry.getKey(); D datum = entry.getValue(); final int localId = key.getLocalId(); final int localIndex = Ids.indexFromLocalId(localId); assertEquals(localIndex, indexIter.nextInt()); assertEquals(localIndex, (int)indexIter2.next()); assertNotNull(entry); assertSame(key, keyIter.next()); assertSame(datum, valueIter.next()); assertTrue(data.containsKey(key)); assertTrue(keys.contains(key)); assertTrue(entries.contains(entry)); assertTrue(entries.contains(new AbstractMap.SimpleEntry<>(key,datum))); assertFalse(entries.contains(new AbstractMap.SimpleEntry<>(key,RealValue.create(Double.NaN)))); assertFalse(entries.remove(new AbstractMap.SimpleEntry<>(key,RealValue.create(Double.NaN)))); assertFalse(entries.add(entry)); assertTrue(values.contains(datum)); assertTrue(data.containsLocalIndex(localIndex)); assertSame(datum, data.getByLocalIndex(localIndex)); assertSame(datum, data.getByLocalId(localId)); assertNull(data.getByLocalId(Ids.localIdFromParts(Ids.BOUNDARY_VARIABLE_TYPE, localIndex))); assertSame(datum, data.put(key, datum)); assertSame(datum, data.setByLocalIndex(localIndex, datum)); } try { indexIter.next(); fail("expected NoSuchElementException"); } catch (NoSuchElementException ex) { } assertEquals(size, count); DataLayerBase<?,?> oldLayer = data.layer(); DataLayerBase<K,D> newLayer = new DL<>(oldLayer.rootGraph(), DenseFactorGraphData.constructorForType(keyType, baseType)); FactorGraphData<K,D> copy = data.clone(newLayer); assertNotSame(copy, data); assertTrue(data.objectEquals(copy)); Map<K,D> map = new HashMap<>(data); assertEquals(data, map); if (data.isEmpty()) { assertEquals(copy, data); } else if (!data.isView()) { Set<? extends DataEntry<K,D>> copiedEntries = copy.entries(); DataEntry<K,D> firstEntry = Iterables.getFirst(copiedEntries, null); assertTrue(copiedEntries.remove(firstEntry)); assertFalse(copiedEntries.remove(firstEntry)); assertFalse(data.objectEquals(copy)); if (baseType.isAssignableFrom(RealValue.class)) { copy.put(firstEntry.getKey(), baseType.cast(RealValue.create(4444))); assertFalse(data.objectEquals(copy)); } } } }