--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.tests;
+
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertTrue;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+\r
+import java.io.File;\r
+import java.net.InetAddress;\r
+import java.util.HashMap;\r
+import java.util.LinkedList;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Random;\r
+import java.util.TreeMap;\r
+import java.util.TreeSet;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.simantics.databoard.Accessors;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.accessor.Accessor;\r
+import org.simantics.databoard.accessor.ArrayAccessor;\r
+import org.simantics.databoard.accessor.BooleanAccessor;\r
+import org.simantics.databoard.accessor.ByteAccessor;\r
+import org.simantics.databoard.accessor.DoubleAccessor;\r
+import org.simantics.databoard.accessor.FloatAccessor;\r
+import org.simantics.databoard.accessor.IntegerAccessor;\r
+import org.simantics.databoard.accessor.LongAccessor;\r
+import org.simantics.databoard.accessor.MapAccessor;\r
+import org.simantics.databoard.accessor.OptionalAccessor;\r
+import org.simantics.databoard.accessor.RecordAccessor;\r
+import org.simantics.databoard.accessor.StringAccessor;\r
+import org.simantics.databoard.accessor.UnionAccessor;\r
+import org.simantics.databoard.accessor.VariantAccessor;\r
+import org.simantics.databoard.accessor.error.AccessorException;\r
+import org.simantics.databoard.accessor.event.Event;\r
+import org.simantics.databoard.accessor.event.InvalidatedEvent;\r
+import org.simantics.databoard.accessor.file.FileVariantAccessor;\r
+import org.simantics.databoard.accessor.impl.ChangeSet;\r
+import org.simantics.databoard.accessor.impl.CompositeRecord;\r
+import org.simantics.databoard.accessor.impl.DirectoryMap;\r
+import org.simantics.databoard.accessor.impl.EventCollection;\r
+import org.simantics.databoard.accessor.interestset.InterestSet;\r
+import org.simantics.databoard.accessor.wire.WireClient;\r
+import org.simantics.databoard.accessor.wire.WireServer;\r
+import org.simantics.databoard.adapter.AdaptException;\r
+import org.simantics.databoard.binding.ArrayBinding;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.BooleanBinding;\r
+import org.simantics.databoard.binding.ByteBinding;\r
+import org.simantics.databoard.binding.DoubleBinding;\r
+import org.simantics.databoard.binding.FloatBinding;\r
+import org.simantics.databoard.binding.IntegerBinding;\r
+import org.simantics.databoard.binding.LongBinding;\r
+import org.simantics.databoard.binding.MapBinding;\r
+import org.simantics.databoard.binding.OptionalBinding;\r
+import org.simantics.databoard.binding.RecordBinding;\r
+import org.simantics.databoard.binding.StringBinding;\r
+import org.simantics.databoard.binding.UnionBinding;\r
+import org.simantics.databoard.binding.VariantBinding;\r
+import org.simantics.databoard.binding.factory.BindingScheme;\r
+import org.simantics.databoard.binding.factory.MutableBindingFactory;\r
+import org.simantics.databoard.binding.impl.ObjectArrayBinding;\r
+import org.simantics.databoard.binding.mutable.MutableVariant;\r
+import org.simantics.databoard.binding.util.RandomValue;\r
+import org.simantics.databoard.method.Client;\r
+import org.simantics.databoard.method.Server;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.type.UnionType;\r
+import org.simantics.databoard.util.binary.BinaryMemory;\r
+
+/**
+ * o Set Value
+ * o Get Value
+ * o Listening
+ * o apply
+ * o Rollback
+ *
+ * o Java Object
+ * o Memory Binary
+ * o File Binary
+ *
+ * TODO Test {@link InvalidatedEvent}
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class TestAccessor {
+
+ RandomValue rv;
+ Map<Datatype, Binding> repository;\r
+ BindingScheme scheme;\r
+ /////////////////////////////////////
+
+
+ public @Before void init() {\r
+ rv = new RandomValue();\r
+ repository = new HashMap<Datatype, Binding>();\r
+ scheme = new MutableBindingFactory( repository );\r
+ }
+\r
+ public static File createTmpDir()\r
+ {\r
+ String tmp = System.getenv("tmp");\r
+ if (tmp==null) tmp = "c:/temp";\r
+ Random r = new Random();\r
+ String randomName = "tmp-"+(r.nextInt(10000)+10000);\r
+ File tmpDir = new File(tmp+"/"+randomName);\r
+ Boolean ok = tmpDir.mkdirs();\r
+ assertTrue( ok );\r
+ return tmpDir;\r
+ } \r
+\r
+ public boolean isKeyShortEnough(Binding binding, Object value) throws AdaptException {\r
+ String key = (String) Bindings.adapt(value, binding, Bindings.STR_VARIANT); \r
+ return key.length()<=200;\r
+ }\r
+\r
+ public @Test void testWireAccessor() throws Exception {\r
+ System.out.println("Wire accessor test");\r
+ \r
+ // TODO: Fix this!\r
+ if (true) return;\r
+\r
+ for (int i=0; i<10000; i++) {\r
+ Bindings.defaultBindingRepository.clear();\r
+ Bindings.bindingRepository.clear();\r
+ Bindings.serializerRepository.clear();\r
+ repository.clear();\r
+ System.out.println(i+": ");\r
+ rv = new RandomValue(i); \r
+ rv.refereableRecords = false;\r
+ Datatype type = rv.randomType(0, 3);\r
+ Binding binding = scheme.getBindingUnchecked(type);\r
+ Object instance = binding.accept(rv);\r
+// System.out.println(binding.printValue(instance, true));\r
+ Accessor accessor = Accessors.getAccessor(binding, instance);\r
+ \r
+ WireServer wireServer = new WireServer(accessor);\r
+ Server server = new Server(0, wireServer.getMethodInterface());\r
+ WireClient wireClient = new WireClient();\r
+ Client client = new Client(InetAddress.getByName("localhost"), server.getPort(), wireClient.getClientMethodInterface());\r
+ wireClient.setServerMethodInterface(client.getConnection().getRemoteMethodInterface());\r
+ Accessor remoteAccessor = (Accessor) wireClient.getAccessor(null);\r
+ testAccessor( remoteAccessor, false );\r
+ \r
+ wireClient.close();\r
+ client.close();\r
+ server.close();\r
+ }\r
+ \r
+ }\r
+ \r
+ public @Test void testBinaryAccessor() throws Exception {\r
+ System.out.println("Test Binary Memory:");\r
+ \r
+ Datatype type = Datatypes.VARIANT;\r
+ Binding binding = scheme.getBindingUnchecked( type );\r
+ Serializer s = binding.serializer();\r
+ TObjectIntHashMap<Object> identities = new TObjectIntHashMap<Object>();\r
+ \r
+ for (int i=0; i<10000; i++) {\r
+ Bindings.defaultBindingRepository.clear();\r
+ Bindings.bindingRepository.clear();\r
+ Bindings.serializerRepository.clear(); \r
+ repository.clear(); \r
+ rv = new RandomValue(i); \r
+ rv.getRandom().nextLong();\r
+ rv.refereableRecords = false;\r
+ System.out.println(i+": ");\r
+ BinaryMemory ram = new BinaryMemory(0);\r
+ Object instance = binding.accept(rv);\r
+ \r
+ binding.assertInstaceIsValid(instance);\r
+// System.out.println(instance);\r
+ \r
+ identities.clear();\r
+ int size = s.getSize(instance, identities);\r
+ \r
+ ram.setLength(size); \r
+ ram.position(0);\r
+ identities.clear();\r
+ s.serialize(ram, identities, instance);\r
+ identities.clear();\r
+\r
+ ram.position(0L);\r
+ Object instance2 = s.deserialize(ram);\r
+ assertTrue( binding.equals(instance, instance2) );\r
+ binding.assertInstaceIsValid(instance2);\r
+ \r
+ VariantAccessor a = (VariantAccessor) Accessors.getAccessor(ram, type);\r
+ \r
+ testAccessor(a);\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ \r
+ public @Test void testJavaAccessor() throws Exception {\r
+ System.out.println("Test Java Objects:");\r
+ for (int i=0; i<10000; i++) {\r
+ Bindings.defaultBindingRepository.clear();\r
+ Bindings.bindingRepository.clear();\r
+ Bindings.serializerRepository.clear();\r
+ repository.clear(); \r
+ System.out.println(i+": ");\r
+ rv = new RandomValue(i); \r
+ rv.refereableRecords = false;\r
+ Datatype type = rv.randomType(0, 3);\r
+ Binding binding = scheme.getBindingUnchecked(type);\r
+ Object instance = binding.accept(rv);\r
+// System.out.println(binding.printValue(instance, true));\r
+ Accessor accessor = Accessors.getAccessor(binding, instance);\r
+ testAccessor(accessor);\r
+ }\r
+ } \r
+\r
+ /**\r
+ * This test tests composite record by adding 10 fields, and running the \r
+ * composition as a record accessor\r
+ */\r
+ public @Test void testCompositeRecord() throws Exception {\r
+ System.out.println("Test composite accessor");\r
+ for (int i=0; i<100; i++) {\r
+ CompositeRecord record = new CompositeRecord();\r
+ for (int j=1; j<=10; j++) {\r
+ \r
+ Binding binding = Bindings.MUTABLE_VARIANT;\r
+ rv = new RandomValue(i*543+j*23); \r
+ rv.getRandom().nextLong();\r
+ rv.refereableRecords = false; \r
+ MutableVariant instance = (MutableVariant) binding.accept(rv);\r
+ String fieldName = "Field"+j;\r
+ Accessor fa = Accessors.getAccessor(instance.getBinding(), instance.getValue());\r
+ record.addField(fieldName, fa);\r
+ }\r
+ System.out.println(i);\r
+ \r
+ testAccessor( record );\r
+ }\r
+ }\r
+ \r
+ \r
+ public @Test void testFolderMap() throws Exception {\r
+ // 1000 tests proves failure\r
+ for (int i=0; i<100; i++) {\r
+ Bindings.defaultBindingRepository.clear();\r
+ Bindings.bindingRepository.clear();\r
+ Bindings.serializerRepository.clear();\r
+ repository.clear();\r
+ \r
+ System.out.println(i+": ");\r
+ File dir = createTmpDir();\r
+ DirectoryMap map = Accessors.openDirectory(dir);\r
+ Binding keyBinding = Bindings.STR_VARIANT; \r
+ try {\r
+ System.out.println("Test Folder Map: "+dir); \r
+ \r
+ // Create 10 files\r
+ for (int j=0; j<10; j++) {\r
+ rv = new RandomValue(i*231231243+j*213); \r
+ rv.refereableRecords = false;\r
+ \r
+ // Create Key \r
+ String key = "";\r
+ do {\r
+ key = (String) keyBinding.accept(rv);\r
+ } while (key.length() > 240);\r
+ \r
+ // Create value \r
+ Datatype valueType = rv.randomType(0, 2); \r
+ Binding valueBinding = scheme.getBindingUnchecked(valueType);\r
+ Object value = valueBinding.accept(rv); \r
+\r
+ System.out.println(key);\r
+ MutableVariant vv = new MutableVariant(valueBinding, value);\r
+ map.put(Bindings.STR_VARIANT, key, Bindings.MUTABLE_VARIANT, vv);\r
+ }\r
+ \r
+ // Test the map\r
+ testAccessor(map);\r
+ \r
+ } finally {\r
+ // Remove all files in the folder\r
+ map.clear();\r
+ map.close();\r
+ System.out.println( dir.listFiles().length + " files.");\r
+ dir.delete();\r
+ }\r
+ \r
+ }\r
+ \r
+ } \r
+
+ public @Test void testBinaryFile() throws Exception {
+ File tmpFile = File.createTempFile("TestAccessor", ".dat");
+ System.out.println("Test Binary File: "+tmpFile);
+ tmpFile.deleteOnExit();
+ FileVariantAccessor fa = Accessors.createFile(tmpFile);
+ Datatype type = Datatypes.VARIANT;
+ Binding binding = scheme.getBindingUnchecked( type );
+
+ for (int i=0; i<10000; i++) {
+ Bindings.bindingRepository.clear();\r
+ Bindings.serializerRepository.clear();\r
+ Bindings.defaultBindingRepository.clear();\r
+ repository.clear();\r
+ \r
+ System.out.println(i+": ");
+ rv = new RandomValue(i);
+ rv.getRandom().nextLong();
+ rv.refereableRecords = false;
+
+ Object instance = binding.accept(rv);
+ System.out.print(i+": "+ binding.printValueDefinition(instance, true));
+ fa.setValue(binding, instance);
+ testAccessor(fa);
+ }
+ fa.close();
+
+ }
+ \r
+
+ /////////////////////////////////////
+\r
+ public void testAccessor(Accessor a) throws Exception {\r
+ testAccessor(a, true);\r
+ }\r
+
+ public void testAccessor(Accessor a, boolean runTypeSpecific) throws Exception {
+ // Init
+ Datatype type = a.type();
+ Binding binding = scheme.getBindingUnchecked(type);
+ InterestSet is = InterestSet.newInterestSet(type, true, true, true);
+ boolean mutable = !binding.isImmutable();
+
+ // Original value and test value
+ Object origValue = a.getValue(binding);
+ binding.assertInstaceIsValid(origValue);
+ Object testValue = binding.accept(rv);\r
+\r
+ // Test Accessor#getValue(binding, instance);\r
+ Binding mutableBinding = Bindings.getMutableBinding(type);\r
+ Object mutableInstance = mutableBinding.createDefault();\r
+ a.getValue(mutableBinding, mutableInstance);\r
+ assertTrue( Bindings.equals(binding, origValue, mutableBinding, mutableInstance) );\r
+
+ boolean same = binding.equals(origValue, testValue);
+ // Create a reference value and an accessor
+ Object refValue = binding.clone(origValue);
+ Accessor ra = Accessors.getAccessor(binding, refValue);
+
+ if ( mutable ) {
+
+ // Write test, without listeners
+ ra.setValue(binding, testValue);
+ Object refClone = ra.getValue(binding);
+ assertTrue( binding.equals(testValue, refClone) );
+ ra.setValue(binding, binding.clone(origValue) );
+ refClone = ra.getValue(binding);
+ assertTrue( binding.equals(origValue, refClone) );
+
+ // Write test, with listeners
+ ChangeSet cs = new ChangeSet(); // Collects Transformation form origValue to testValue
+ a.addListener(cs, is, null, null);
+ a.setValue(binding, testValue);
+ // There must be events in change set
+ if (!same) assertFalse(cs.isEmpty());
+
+ // Verify the accessor now contains the test value
+ Object x = a.getValue(binding);
+ assertTrue( binding.equals(testValue, x ) );
+
+ // Convert reference value to testValue
+ LinkedList<Event> rollback = new LinkedList<Event>();
+ List<Event> events = cs.getAndClearEvents(); // Transformation form origValue to testValue
+ ra.apply(events, rollback); // Apply transformation from origValue to testValue, and gather rollback, a transformation from testValue to origValue
+ x = ra.getValue(binding);
+ assertTrue( binding.equals(x, testValue) );
+
+ // Revert reference value to origValue using rollback
+ a.removeListener(cs);\r
+ a.apply(rollback, null); // Apply transformation from testValue to origValue
+ x = a.getValue(binding);
+ assertTrue( binding.equals( x, origValue ) );
+ }
+
+ // Ensure the accessor has the correct value
+ Object x = a.getValue(binding);\r
+ assertTrue( binding.equals( x, origValue) );\r
+ \r
+ if (runTypeSpecific) {\r
+ // Type specific tests
+ if (a instanceof ArrayAccessor) testArrayAccessor((ArrayAccessor) a);
+ if (a instanceof RecordAccessor) testRecordAccessor((RecordAccessor) a);
+ if (a instanceof MapAccessor) testMapAccessor((MapAccessor) a);
+ if (a instanceof BooleanAccessor) testBooleanAccessor((BooleanAccessor) a);
+ if (a instanceof ByteAccessor) testByteAccessor((ByteAccessor) a);
+ if (a instanceof DoubleAccessor) testDoubleAccessor((DoubleAccessor) a);
+ if (a instanceof FloatAccessor) testFloatAccessor((FloatAccessor) a);
+ if (a instanceof IntegerAccessor) testIntegerAccessor((IntegerAccessor) a);
+ if (a instanceof LongAccessor) testLongAccessor((LongAccessor) a);
+ if (a instanceof OptionalAccessor) testOptionalAccessor((OptionalAccessor) a);
+ if (a instanceof StringAccessor) testStringAccessor((StringAccessor) a);
+ if (a instanceof UnionAccessor) testUnionAccessor((UnionAccessor) a);
+ if (a instanceof VariantAccessor) testVariantAccessor((VariantAccessor) a);
+
+ // Ensure the accessor has the correct value
+ a.setValue(binding, origValue);
+ x = a.getValue(binding);\r
+ assertTrue( binding.equals( x, origValue) );\r
+ }
+ }
+
+ public void testMapAccessor(MapAccessor a) throws Exception {
+ Datatype type = a.type();
+ MapBinding binding = (MapBinding) scheme.getBindingUnchecked(type);
+ Binding kb = binding.getKeyBinding();
+ Binding vb = binding.getValueBinding();
+ InterestSet is = InterestSet.newInterestSet(type, true, true, false);
+ boolean mutable = !binding.isImmutable();
+ int len = a.size();
+
+ // getAll(Binding, Binding, Object[], Object[])
+ Object oks[] = new Object[ len ];
+ Object ovs[] = new Object[ len ];
+ a.getAll(kb, vb, oks, ovs);
+\r
+ // getAll(Binding, Binding, Map<Object, Object>)
+ TreeMap<Object, Object> om = new TreeMap<Object, Object>(kb);
+ a.getAll(kb, vb, om);
+
+ // getKeys(Binding), getValues(Binding)
+ Object oks2[] = a.getKeys(kb);
+ Object ovs2[] = a.getValues(vb);
+
+ // assert the results are the same for the getAll()s and getKeys and getValues
+ for (int i=0; i<len; i++) {
+ assertTrue( om.containsKey(oks[i]) );
+ assertTrue( om.containsKey(oks2[i]) );
+ Object v = om.get(oks[i]);
+ assertTrue( vb.equals( v, ovs[i] ) );
+ assertTrue( vb.equals( v, ovs2[i] ) );
+ v = om.get(oks2[i]);
+ assertTrue( vb.equals( v, ovs[i] ) );
+ assertTrue( vb.equals( v, ovs2[i] ) );
+ }
+\r
+ // Test Get entries\r
+ if (len>2) {\r
+ // Get all\r
+ try {\r
+ Object keys[] = new Object[ len ];\r
+ Object values[] = new Object[ len ];\r
+ int c = a.getEntries(kb, a.getFirstKey(kb), true, a.getLastKey(kb), true, \r
+ new ObjectArrayBinding(kb), keys, \r
+ new ObjectArrayBinding(vb), values, -1);\r
+ \r
+ assertEquals(len, c);\r
+ for (int i=0; i<len; i++) { \r
+ assertTrue( kb.equals( oks[i], keys[i] ) );\r
+ assertTrue( vb.equals( ovs[i], values[i] ) );\r
+ }\r
+ \r
+ // Exclude first and last\r
+ keys = new Object[ len-2 ];\r
+ values = new Object[ len-2 ];\r
+ c = a.getEntries(kb, a.getFirstKey(kb), false, a.getLastKey(kb), false, \r
+ new ObjectArrayBinding(kb), keys, \r
+ new ObjectArrayBinding(vb), values, -1);\r
+ assertEquals(len-2, c);\r
+ for (int i=1; i<len-1; i++) { \r
+ assertTrue( kb.equals( oks[i], keys[i-1] ) );\r
+ assertTrue( vb.equals( ovs[i], values[i-1] ) );\r
+ }\r
+ \r
+ // Get one\r
+ c = a.getEntries(kb, a.getFirstKey(kb), true, a.getLastKey(kb), false, \r
+ new ObjectArrayBinding(kb), keys, \r
+ new ObjectArrayBinding(vb), values, 1);\r
+ assertEquals(1, c);\r
+ assertTrue( kb.equals( oks[0], keys[0] ) );\r
+ assertTrue( vb.equals( ovs[0], values[0] ) );\r
+ }\r
+ catch (AccessorException e) {\r
+ assertEquals( "Not implemented", e.getMessage() );\r
+ }\r
+ \r
+ }
+
+ // Create test values
+ TreeSet<Object> keys = new TreeSet<Object>(kb);
+ for (int i=0; i<10; i++) {\r
+ Object key = null;\r
+ if (kb.type().equals(Datatypes.VARIANT)) {\r
+ do {\r
+ key = kb.accept(rv);\r
+ } while( !kb.type().equals(Datatypes.VARIANT) || !isKeyShortEnough(kb, key) ); \r
+ } else {\r
+ key = kb.accept(rv); \r
+ }\r
+ keys.add( key );\r
+ }
+ int testValueCount = keys.size();
+ Object tks[] = keys.toArray( new Object[testValueCount] );
+ Object tvs[] = new Object[ testValueCount ];
+ for (int i=0; i<testValueCount; i++) tvs[i] = vb.accept(rv);
+
+ if (len>=3) {
+ // getFirstKey(Binding)
+ Object fk = a.getFirstKey(kb);
+ assertTrue( kb.equals(fk, oks[0]) );
+
+ // getLastKey(Binding)
+ Object lk = a.getLastKey(kb);\r
+ assertTrue( kb.equals(lk, oks[len-1]) );
+
+ // getLowerKey(Binding, Object)
+ Object k = a.getLowerKey(kb, fk);
+ assertNull(k); \r
+ k = a.getLowerKey(kb, lk);
+ assertTrue( kb.equals(k, oks[len-2]) );
+
+ // getFloorKey(Binding, Object)
+ k = a.getFloorKey(kb, fk);
+ assertTrue( kb.equals(k, oks[0]) );
+ k = a.getFloorKey(kb, lk);
+ assertTrue( kb.equals(k, oks[len-1]) );
+
+ // getCeilingKey(Binding, Object)
+ k = a.getCeilingKey(kb, lk);
+ assertTrue( kb.equals(k, oks[len-1]) );
+ k = a.getCeilingKey(kb, fk);
+ assertTrue( kb.equals(k, oks[0]) );
+
+ // getHigherKey(Binding, Object)
+ k = a.getHigherKey(kb, lk);\r
+ assertNull(k);
+ k = a.getHigherKey(kb, fk);
+ assertTrue( kb.equals(k, oks[1]) );
+ }
+
+ // clear
+ // putAll(Binding, Binding, Object[], Object[])
+ a.clear();
+ int size = a.size();\r
+ assertEquals( 0, size );
+ a.putAll(kb, vb, oks, ovs);\r
+ size = a.size(); \r
+ assertEquals( len, size );
+
+ // clear
+ // putAll(Binding, Binding, Map<Object, Object>)
+ a.clear();
+ assertEquals( 0, a.size() );
+ a.putAll(kb, vb, om);
+ assertEquals( len, a.size() );
+
+ // containsKey
+ // containsValue
+ for (int i=0; i<len; i++) {
+ assertTrue( a.containsKey(kb, oks[i]) );
+ assertTrue( a.containsValue(vb, ovs[i]) );
+ }
+
+ // Add, Remove
+ if ( mutable ) {
+ // put (insert)
+ int count = len;
+ for (int i=0; i<testValueCount; i++) {
+ if (!a.containsKey(kb, tks[i])) count++;
+ a.put(kb, tks[i], vb, tvs[i]);
+ }
+ assertEquals(count, a.size());
+ for (int i=0; i<testValueCount; i++) {
+ Object o = a.get(kb, tks[i], vb);
+ assertTrue( vb.equals(tvs[i], o) );
+ }
+ // remove(Binding, Object)
+ for (int i=0; i<testValueCount; i++) {
+ a.remove(kb, tks[i]);
+ }
+ for (int i=0; i<len; i++) {
+ a.remove(kb, oks[i]);
+ }
+ a.putAll(kb, vb, oks, ovs);
+ }
+
+ // Set
+ int common = Math.min(len, testValueCount);
+
+ for (int i=0; i<common; i++) {
+ a.put(kb, oks[i], vb, tvs[i]);
+ Object x = a.get(kb, oks[i], vb);
+ assertTrue( vb.equals( tvs[i], x) );
+ }
+ for (int i=0; i<common; i++) {
+ a.put(kb, oks[i], vb, ovs[i]);
+ Object x = a.get(kb, oks[i], vb);
+ assertTrue( vb.equals( ovs[i], x ) );
+ }
+
+ //// Test sub-accessors with recursion
+ for (int i=0; i<len; i++) {
+ Accessor sa = a.getValueAccessor(kb, oks[i]);
+ testAccessor(sa);
+ }
+ }
+
+ public void testArrayAccessor(ArrayAccessor a) throws Exception {
+ Datatype type = a.type();
+ ArrayBinding binding = (ArrayBinding) scheme.getBindingUnchecked(type);
+ Binding cb = binding.getComponentBinding();
+ InterestSet is = InterestSet.newInterestSet(type, true, true, false);
+ boolean mutable = !binding.isImmutable();
+
+ int len = a.size();
+ Object ovs[] = new Object[ len ];
+ a.getAll(cb, ovs);
+
+ //// Create test values
+ int testValueCount = rv.getRandom().nextInt(10)+10;
+ Object tvs[] = new Object[ testValueCount ];
+ Object tvs2[] = new Object[ testValueCount ];
+ for (int i=0; i<testValueCount; i++) {
+ tvs[i] = cb.accept(rv);
+ tvs2[i] = cb.accept(rv);
+ }
+
+ // Add, Remove
+ if ( mutable ) {
+
+ //// Add in values to end
+ a.addAll(cb, tvs);
+ // Test get
+ for (int i=0; i<testValueCount; i++) {
+ Object o1 = a.get(i + len, cb);
+ Object o2 = tvs[i];
+ assertTrue( cb.equals(o1, o2) );
+ }\r
+
+ // Test get to existing instance\r
+ {\r
+ Object o1 = cb.createDefault();\r
+ for (int i=0; i<testValueCount; i++) {\r
+ a.get(i + len, cb, o1);\r
+ Object o2 = tvs[i];\r
+ assertTrue( cb.equals(o1, o2) );\r
+ }\r
+ }\r
+\r
+ // Test getAll
+ Object all[] = new Object[ testValueCount + len ];
+ a.getAll(cb, all);
+ for (int i=0; i<testValueCount; i++) {
+ Object o1 = all[i+len];
+ Object o2 = tvs[i];
+ assertTrue( cb.equals(o1, o2) );
+ }
+ a.remove(len, testValueCount);
+ for (int i=0; i<len; i++) {
+ Object o1 = ovs[i];
+ Object o2 = a.get(i, cb);
+ assertTrue( cb.equals(o1, o2) );
+ }
+ assertEquals(len, a.size());
+
+
+ //// Add in values to the beginning
+ a.addAll(0, cb, tvs);
+ for (int i=0; i<testValueCount; i++) {
+ Object o1 = a.get(i, cb);
+ Object o2 = tvs[i];
+ assertTrue( cb.equals(o1, o2) );
+ }
+ // Test getAll
+ a.getAll(cb, all);
+ for (int i=0; i<testValueCount; i++) {
+ Object o1 = all[i];
+ Object o2 = tvs[i];
+ assertTrue( cb.equals(o1, o2) );
+ }
+ a.remove(0, testValueCount);
+ assertEquals(len, a.size());
+ }\r
+ \r
+ int oldSize = a.size();\r
+ a.setSize( oldSize + 10);\r
+ assertEquals( oldSize+10, a.size() );\r
+ a.setSize( oldSize );
+ assertEquals( oldSize, a.size() );\r
+
+ //// Test setValue()
+ int common = Math.min(len, testValueCount);
+ for (int i=0; i<common; i++) \r
+ a.set(i, cb, tvs[i]);\r
+
+ for (int i=0; i<common; i++) assertTrue( cb.equals( tvs[i], a.get(i, cb)) );
+ for (int i=0; i<common; i++) a.set(i, cb, ovs[i]);
+ for (int i=0; i<common; i++) assertTrue( cb.equals( ovs[i], a.get(i, cb)) );
+
+ //// Test sub-accessors with recursion
+ for (int i=0; i<len; i++) {
+ Accessor sa = a.getAccessor(i);
+ testAccessor(sa);
+ }
+
+ }
+
+ public void testRecordAccessor(RecordAccessor a) throws Exception {
+ Datatype type = a.type();
+ RecordBinding binding = (RecordBinding) scheme.getBindingUnchecked(type);
+ Binding cbs[] = binding.getComponentBindings();
+ InterestSet is = InterestSet.newInterestSet(type, true, true, false);
+
+ int len = a.count();
+ Object ovs[] = new Object[ len ];
+ for (int i=0; i<len; i++) ovs[i] = a.getFieldValue(i, cbs[i]);
+
+ //// Create test values
+ Object tvs[] = new Object[ len ];
+ Object tvs2[] = new Object[ len ];
+ for (int i=0; i<len; i++) {
+ tvs[i] = cbs[i].accept(rv);
+ tvs2[i] = cbs[i].accept(rv);
+ }
+
+ //// Test setValue()\r
+// System.gc();
+ for (int i=0; i<len; i++) \r
+ a.setFieldValue(i, cbs[i], tvs[i]);
+ for (int i=0; i<len; i++) assertTrue( cbs[i].equals( tvs[i], a.getFieldValue(i, cbs[i])) );
+ for (int i=0; i<len; i++) a.setFieldValue(i, cbs[i], ovs[i]);
+ for (int i=0; i<len; i++) assertTrue( cbs[i].equals( ovs[i], a.getFieldValue(i, cbs[i])) );\r
+
+ //// Test sub-accessors with recursion
+ for (int i=0; i<len; i++) {
+ Accessor sa = a.getFieldAccessor(i);
+ testAccessor(sa);
+ }
+
+ }
+
+ public void testOptionalAccessor(OptionalAccessor a) throws Exception {
+ Datatype type = a.type();
+ OptionalBinding binding = (OptionalBinding) scheme.getBindingUnchecked(type);
+ Binding cb = binding.getComponentBinding();
+ InterestSet is = InterestSet.newInterestSet(type, true, true, true);
+
+ // Remember original value
+ boolean hadValue = a.hasValue();
+ Object ov = hadValue ? a.getComponentValue(cb) : null;
+ Object tv = cb.accept(rv);
+
+ a.setComponentValue(cb, tv);
+ assertTrue( cb.equals(a.getComponentValue(cb), tv) );
+ assertEquals( true, a.hasValue());
+
+ a.setNoValue();
+ assertEquals( false, a.hasValue());
+
+ // Test Invalidated Event
+ {
+ a.setNoValue();
+ a.setComponentValue(cb, tv);
+ Accessor sa = a.getComponentAccessor();
+ EventCollection ec = new EventCollection();
+ a.addListener(ec, is, null, null);
+ a.setNoValue();
+ a.removeListener(ec);
+ boolean invalidatedEventOk = false;
+ for (Event e : ec.getAndClearEvents()) {
+ invalidatedEventOk |= (e instanceof InvalidatedEvent) && (e.reference !=null);
+ }
+ sa.getClass();
+ assertTrue( invalidatedEventOk );
+ }
+
+ // Restore value
+ if (hadValue) {
+ a.setComponentValue(cb, ov);
+ } else {
+ a.setNoValue();
+ }
+ }
+
+ public void testUnionAccessor(UnionAccessor a) throws Exception {
+ UnionType type = a.type();
+ UnionBinding binding = (UnionBinding) scheme.getBindingUnchecked(type);
+ Binding cbs[] = binding.getComponentBindings();
+ InterestSet is = InterestSet.newInterestSet(type, true, true, true);
+ int len = a.count();
+
+ // Get original values
+ int ot = a.getTag();
+ Object ov = a.getComponentValue(cbs[ot]);
+
+ //// Create test values
+ Object tvs[] = new Object[ len ];
+ Object tvs2[] = new Object[ len ];
+ for (int i=0; i<len; i++) {
+ tvs[i] = cbs[i].accept(rv);
+ tvs2[i] = cbs[i].accept(rv);
+ }
+
+ //// Test setValue()
+ for (int i=0; i<len; i++) {
+ a.setComponentValue(i, cbs[i], tvs[i]);
+ assertEquals( i, a.getTag() );
+ assertTrue( Bindings.equals(cbs[i], a.getComponentValue(cbs[i]), cbs[i], tvs[i]) );
+ }
+
+ // Test Invalidated Event
+ if (type.getComponentCount()>1)
+ {
+ int i=0;
+ a.setComponentValue(i, cbs[i], tvs[i]);
+ Accessor sa = a.getComponentAccessor();
+ EventCollection ec = new EventCollection();
+ a.addListener(ec, is, null, null);
+ i = 1;
+ a.setComponentValue(i, cbs[i], tvs[i]);
+ boolean invalidatedEventOk = false;
+ List<Event> events = ec.getAndClearEvents();
+ for (Event e : events) {
+ invalidatedEventOk |= (e instanceof InvalidatedEvent) && (e.reference !=null);
+ }
+ a.removeListener(ec);
+ sa.getClass();
+ assertTrue( invalidatedEventOk );
+ }
+
+ a.setComponentValue(ot, cbs[ot], ov);
+
+ //// Test sub-accessors with recursion
+ Accessor sa = a.getComponentAccessor();
+ testAccessor(sa);
+
+ }
+
+ public void testVariantAccessor(VariantAccessor a) throws Exception {
+ Datatype type = a.type();
+ VariantBinding binding = (VariantBinding) scheme.getBindingUnchecked(type);
+ InterestSet is = InterestSet.newInterestSet(type, true, true, true);
+
+ // Remember the original value
+ Binding ob = scheme.getBindingUnchecked( type );
+ Object ov = a.getValue(ob);
+ ob.assertInstaceIsValid(ov);
+ boolean mutable = !binding.isImmutable();
+
+ if (mutable) {
+ // Create test values
+ int testValueCount = 10;
+ Binding tvb[] = new Binding[testValueCount];
+ Object tvs[] = new Object[testValueCount];
+ for (int i=0; i<testValueCount; i++) {
+ tvb[i] = scheme.getBindingUnchecked( rv.randomType(0, 2) );
+ tvs[i] = tvb[i].accept(rv);
+ }
+
+ // Set & Get
+ for (int i=0; i<testValueCount; i++) {
+ a.setContentValue(tvb[i], tvs[i]);
+ Object o = a.getContentValue(tvb[i]);
+ assertTrue( tvb[i].equals(o, tvs[i]) );
+ }
+
+ // Test Invalidated Event
+ {
+ Binding tb = tvb[1];
+ Object tv = tvs[1];
+ Datatype ct = tvb[0].type();
+ a.setContentValue(tvb[0], tvs[0]);
+ EventCollection ec = new EventCollection();
+ a.addListener(ec, is, null, null);
+ Accessor sa = a.getContentAccessor();
+ a.setContentValue(tvb[1], tvs[1]);
+ a.removeListener(ec);
+
+ // Assigned same type
+ if (ct.getClass().equals(tb.type().getClass())) {
+
+ } else {
+ boolean invalidatedEventOk = false;
+ List<Event> events = ec.getAndClearEvents();
+ for (Event e : events) {
+ invalidatedEventOk |= (e instanceof InvalidatedEvent) && (e.reference !=null);
+ }
+ assertTrue( invalidatedEventOk );
+ }
+ }
+ }
+
+ //// Test sub-accessors with recursion
+ Accessor sa = a.getContentAccessor();
+ testAccessor(sa);
+
+ // Restore
+ a.setValue(ob, ov);
+ }
+
+ public void testByteAccessor(ByteAccessor a) throws Exception {
+ byte ov = a.getValue();
+ ByteBinding b = Bindings.BYTE;
+ for (int i=0; i<10; i++) {
+ Byte r = (Byte) rv.visit(b);
+ a.setValue(r);
+ assertTrue( r == a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+ public void testDoubleAccessor(DoubleAccessor a) throws Exception {
+ double ov = a.getValue();
+ DoubleBinding b = Bindings.DOUBLE;
+ for (int i=0; i<10; i++) {
+ Double r = (Double) rv.visit(b);
+ a.setValue(r);
+ assertTrue( r == a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+ public void testFloatAccessor(FloatAccessor a) throws Exception {
+ float ov = a.getValue();
+ FloatBinding b = Bindings.FLOAT;
+ for (int i=0; i<10; i++) {
+ Float r = (Float) rv.visit(b);
+ a.setValue(r);
+ assertTrue( r == a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+ public void testIntegerAccessor(IntegerAccessor a) throws Exception {
+ int ov = a.getValue();
+ IntegerBinding b = Bindings.INTEGER;
+ for (int i=0; i<10; i++) {
+ Integer r = (Integer) rv.visit(b);
+ a.setValue(r);
+ assertTrue( r == a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+ public void testLongAccessor(LongAccessor a) throws Exception {
+ long ov = a.getValue();
+ LongBinding b = Bindings.LONG;
+ for (int i=0; i<10; i++) {
+ Long r = (Long) rv.visit(b);
+ a.setValue(r);
+ assertTrue( r == a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+ public void testStringAccessor(StringAccessor a) throws Exception {
+ String ov = a.getValue();
+ StringBinding b = Bindings.STRING;
+ for (int i=0; i<10; i++) {
+ String r = (String) rv.visit(b);
+ a.setValue(r);
+ assertEquals( r, a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+ public void testBooleanAccessor(BooleanAccessor a) throws Exception {
+ Boolean ov = a.getValue();
+ BooleanBinding b = Bindings.BOOLEAN;
+ for (int i=0; i<10; i++) {
+ Boolean r = (Boolean) rv.visit(b);
+ a.setValue(r);
+ assertEquals( r, a.getValue() );
+ }
+ a.setValue(ov);
+ }
+
+
+}
+