/******************************************************************************* * 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 java.util.Objects.*; import static org.junit.Assert.*; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.junit.Test; import com.analog.lyric.dimple.data.DataDensity; 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.GenericDataLayer; import com.analog.lyric.dimple.data.IDatum; import com.analog.lyric.dimple.data.SparseFactorGraphData; import com.analog.lyric.dimple.data.ValueDataLayer; 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.core.Node; import com.analog.lyric.dimple.model.sugar.ModelSyntacticSugar.CurrentModel; import com.analog.lyric.dimple.model.values.RealValue; import com.analog.lyric.dimple.model.values.Value; 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 DataLayerBase}. * <p> * @since 0.08 * @author Christopher Barber */ public class TestDataLayer extends DimpleTestBase { @Test public void test() { FactorGraph root = new FactorGraph("root"), nested1, nested2, nested3; try (CurrentModel cur = using(root)) { reals("a", 100); nested1 = root.addGraph(new FactorGraph()); nested2 = root.addGraph(new FactorGraph()); try (CurrentModel cur1 = using(nested1)) { reals("b", 50); nested3 = nested2.addGraph(new FactorGraph()); try (CurrentModel cur3 = using(nested3)) { reals("c", 50); } } try (CurrentModel cur2 = using(nested2)) { reals("d", 50); } } test(root, DenseFactorGraphData.constructorForType(Variable.class, IDatum.class)); test(root, DenseFactorGraphData.constructorForType(Variable.class, Value.class)); test(root, SparseFactorGraphData.constructorForType(Variable.class, IDatum.class)); ValueDataLayer sampleLayer = ValueDataLayer.dense(root); assertSame(Value.class, sampleLayer.baseType()); test(sampleLayer); ValueDataLayer sampleLayer2 = new ValueDataLayer(nested3); assertSame(root, sampleLayer2.rootGraph()); DataLayer<RealValue> sampleLayer3 = new DataLayer<>(root, DataDensity.DENSE, RealValue.class); assertSame(RealValue.class, sampleLayer3.baseType()); assertSame(DenseFactorGraphData.class, sampleLayer3.createDataForGraph(root).getClass()); test(sampleLayer3); DataLayerBase<?,?> sparse = new DataLayer<>(root, DataDensity.SPARSE, Value.class); assertSame(Value.class, sparse.baseType()); assertSame(SparseFactorGraphData.class, sparse.createDataForGraph(root).getClass()); test(new GenericDataLayer(root)); } <D extends IDatum> void test(FactorGraph graph, FactorGraphData.Constructor<Variable,D> constructor) { DataLayerBase<Variable,D> layer = new DataLayer<D>(graph, constructor); assertSame(constructor, layer.dataConstructor()); test(layer); } <D extends IDatum> void test(DataLayerBase<Variable, D> layer) { FactorGraph root = layer.rootGraph(); assertEquals(0, layer.size()); assertInvariants(layer); Set<Variable> dataVars = new HashSet<>(); final ArrayList<Variable> allVars = new ArrayList<>(root.getVariables()); for (int i = 0; i < 25; ++i) { Variable var = allVars.get(testRand.nextInt(allVars.size())); if (dataVars.add(var)) { assertFalse(layer.containsKey(var)); assertNull(layer.get(var)); assertNull(layer.put(var, null)); assertNull(layer.get(var)); Value value = RealValue.create(i); assertNull(layer.put(var, layer.baseType().cast(value))); assertSame(value, layer.get(var)); if (layer instanceof DataLayer) { DataLayer<D> dataLayer = (DataLayer<D>)layer; dataLayer.set(var, null); assertNull(layer.get(var)); dataLayer.set(var, value.getObject()); assertNotSame(value, layer.get(var)); assertTrue(value.valueEquals(requireNonNull((Value)(layer.get(var))))); dataLayer.set(var, value.getObject()); assertTrue(value.valueEquals(requireNonNull((Value)(layer.get(var))))); expectThrow(ClassCastException.class, layer, "set", var, "bogus"); dataLayer.set(var, value); assertSame(value, layer.get(var)); } } assertEquals(dataVars.size(), layer.size()); } assertInvariants(layer); Map<Variable,D> copy = new HashMap<>(layer); assertEquals(layer.size(), copy.size()); assertEquals(copy, layer); layer.clear(); assertTrue(layer.isEmpty()); assertInvariants(layer); FactorGraphData<Variable,D> fgd = layer.getDataForGraph(root); assertTrue(fgd == null || fgd.isEmpty()); layer.putAll(copy); assertEquals(copy, layer); layer.entrySet().clear(); assertTrue(layer.isEmpty()); assertInvariants(layer); layer.putAll(copy); layer.keySet().clear(); assertTrue(layer.isEmpty()); assertInvariants(layer); layer.putAll(copy); Set<Variable> removeVars = new HashSet<>(); for (Variable var : Iterables.limit(dataVars, 3)) { removeVars.add(var); } for (Variable var : removeVars) { assertSame(layer.get(var), layer.remove(var)); assertNull(layer.remove(var)); assertFalse(layer.containsKey(var)); } assertEquals(copy.size() - 3, layer.size()); assertInvariants(layer); for (Variable var : removeVars) { assertTrue(layer.entrySet().add(new AbstractMap.SimpleEntry<>(var, copy.get(var)))); } assertEquals(copy, layer); for (Variable var : removeVars) { assertTrue(layer.keySet().remove(var)); assertFalse(layer.keySet().remove(var)); } assertEquals(copy.size() - 3, layer.size()); assertInvariants(layer); for (Variable var : removeVars) { assertNull(layer.put(var, copy.get(var))); } assertEquals(copy, layer); for (Variable var : removeVars) { assertTrue(layer.entrySet().remove(new AbstractMap.SimpleEntry<>(var, copy.get(var)))); } assertEquals(copy.size() - 3, layer.size()); assertInvariants(layer); for (Variable var : removeVars) { assertNull(layer.put(var, copy.get(var))); } assertEquals(copy, layer); FactorGraphData<Variable,D> oldData = requireNonNull(layer.getDataForGraph(root)); assertSame(oldData, layer.removeDataForGraph(root)); assertNull(layer.removeDataForGraph(root)); for (Variable var : oldData.keySet()) { assertFalse(layer.containsKey(var)); assertNull(layer.getByGraphTreeId(var.getGraphTreeId())); } assertEquals(copy.size() - oldData.size(), layer.size()); assertInvariants(layer); assertNull(layer.setDataForGraph(oldData)); assertSame(oldData, layer.setDataForGraph(oldData)); expectThrow(IllegalArgumentException.class, layer, "put", new Real(), null); // DataLayer<IDatum> layer2 = new DataLayer<>(root); // expectThrow(IllegalArgumentException.class, layer2, "setDataForGraph", layer.getDataForGraph(root)); } public static <K extends IFactorGraphChild, D extends IDatum> void assertInvariants(DataLayerBase<K,D> layer) { final Class<K> keyType = layer.keyType(); final Class<D> baseType = layer.baseType(); final FactorGraph root = layer.rootGraph(); assertTrue(layer.sharesRoot(root)); assertEquals(baseType.isAssignableFrom(Value.class) || Value.class.isAssignableFrom(baseType), layer.allowsValues()); assertFalse(layer.containsKey("not a variable")); assertNull(layer.getDataForGraph(new FactorGraph())); assertNull(layer.removeDataForGraph(new FactorGraph())); assertNull(layer.get(new Real())); assertNull(layer.remove("not a variable")); int sizeFromData = 0; for (FactorGraphData<?,?> data : layer.getData()) { assertSame(data, layer.getDataForGraph(data.graph())); TestFactorGraphData.assertInvariants(data); sizeFromData += data.size(); } final int size = layer.size(); assertEquals(sizeFromData, size); assertEquals(size == 0, layer.isEmpty()); Set<K> keys = layer.keySet(); Set<Map.Entry<K, D>> entries = layer.entrySet(); Collection<D> values = layer.values(); assertEquals(size, keys.size()); assertEquals(size, entries.size()); assertEquals(size, values.size()); assertFalse(keys.contains("not a key")); assertFalse(keys.contains(new Real())); assertFalse(entries.contains("not an entry")); assertFalse(keys.remove("not a key")); assertFalse(keys.remove(new Real())); assertFalse(entries.remove("not an entry")); int count = 0; Iterator<K> keyIter = keys.iterator(); Iterator<Map.Entry<K,D>> entryIter = entries.iterator(); Iterator<D> valueIter = values.iterator(); while (entryIter.hasNext()) { ++count; assertTrue(keyIter.hasNext()); assertTrue(valueIter.hasNext()); Map.Entry<K,D> entry = entryIter.next(); K key = entry.getKey(); IDatum datum = entry.getValue(); assertSame(key, keyIter.next()); assertSame(datum, valueIter.next()); assertTrue(layer.containsKey(key)); assertTrue(layer.containsDataFor(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)); long graphTreeId = key.getGraphTreeId(); assertSame(datum, layer.getByGraphTreeId(graphTreeId)); assertSame(datum, layer.get(graphTreeId)); assertSame(datum, layer.get(key.getGlobalId())); if (Node.class.isAssignableFrom(keyType)) { assertSame(datum, layer.get(((Node)key).getQualifiedName())); } int graphTreeIndex = Ids.graphTreeIndexFromGraphTreeId(graphTreeId); int localId = Ids.localIdFromGraphTreeId(graphTreeId); int localIndex = Ids.indexFromLocalId(localId); assertSame(datum, layer.getByGraphTreeAndLocalIndices(graphTreeIndex, localIndex)); int bogusLocalId = Ids.localIdFromParts(Ids.BOUNDARY_VARIABLE_TYPE, localIndex); assertNull(layer.getByGraphTreeId(Ids.graphTreeIdFromParts(graphTreeIndex, bogusLocalId))); } assertFalse(keyIter.hasNext()); assertFalse(valueIter.hasNext()); assertEquals(size, count); assertTrue(layer.objectEquals(layer)); assertFalse(layer.objectEquals(null)); assertFalse(layer.objectEquals("bogus")); assertFalse(layer.objectEquals(new GenericDataLayer(new FactorGraph(), DataDensity.DENSE))); DataLayerBase<K,D> copy = layer.clone(); assertTrue(layer.objectEquals(copy)); Map<K,D> map = new HashMap<>(layer); assertEquals(layer, map); if (layer.isEmpty()) { assertEquals(copy, layer); FactorGraphData<K,D> data = copy.createDataForGraph(root); expectThrow(IllegalArgumentException.class, layer, "setDataForGraph", data); assertTrue(layer.objectEquals(copy)); assertTrue(copy.objectEquals(layer)); if (Variable.class.isAssignableFrom(keyType) && !layer.isView()) { Variable var = root.getOwnedVariables().iterator().next(); copy.put(keyType.cast(var), baseType.cast(RealValue.create(234.234))); assertFalse(layer.objectEquals(copy)); assertFalse(copy.objectEquals(layer)); } } else if (!layer.isView()) { assertEquals(copy, layer); if (Variable.class.isAssignableFrom(keyType)) { Variable var = (Variable)layer.keySet().iterator().next(); assertNotNull(copy.put(keyType.cast(var), baseType.cast(RealValue.create(234.234)))); assertFalse(layer.objectEquals(copy)); assertFalse(copy.objectEquals(layer)); } } } }