]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/testcases/org/simantics/databoard/tests/TestAccessor.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / testcases / org / simantics / databoard / tests / TestAccessor.java
1 /*******************************************************************************
2  *  Copyright (c) 2010 Association for Decentralized Information Management in
3  *  Industry THTH ry.
4  *  All rights reserved. This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License v1.0
6  *  which accompanies this distribution, and is available at
7  *  http://www.eclipse.org/legal/epl-v10.html
8  *
9  *  Contributors:
10  *      VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.tests;
13
14 import static org.junit.Assert.assertEquals;
15 import static org.junit.Assert.assertFalse;
16 import static org.junit.Assert.assertNull;
17 import static org.junit.Assert.assertTrue;
18 import gnu.trove.map.hash.TObjectIntHashMap;
19
20 import java.io.File;
21 import java.net.InetAddress;
22 import java.util.HashMap;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Random;
27 import java.util.TreeMap;
28 import java.util.TreeSet;
29
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.simantics.databoard.Accessors;
33 import org.simantics.databoard.Bindings;
34 import org.simantics.databoard.Datatypes;
35 import org.simantics.databoard.accessor.Accessor;
36 import org.simantics.databoard.accessor.ArrayAccessor;
37 import org.simantics.databoard.accessor.BooleanAccessor;
38 import org.simantics.databoard.accessor.ByteAccessor;
39 import org.simantics.databoard.accessor.DoubleAccessor;
40 import org.simantics.databoard.accessor.FloatAccessor;
41 import org.simantics.databoard.accessor.IntegerAccessor;
42 import org.simantics.databoard.accessor.LongAccessor;
43 import org.simantics.databoard.accessor.MapAccessor;
44 import org.simantics.databoard.accessor.OptionalAccessor;
45 import org.simantics.databoard.accessor.RecordAccessor;
46 import org.simantics.databoard.accessor.StringAccessor;
47 import org.simantics.databoard.accessor.UnionAccessor;
48 import org.simantics.databoard.accessor.VariantAccessor;
49 import org.simantics.databoard.accessor.error.AccessorException;
50 import org.simantics.databoard.accessor.event.Event;
51 import org.simantics.databoard.accessor.event.InvalidatedEvent;
52 import org.simantics.databoard.accessor.file.FileVariantAccessor;
53 import org.simantics.databoard.accessor.impl.ChangeSet;
54 import org.simantics.databoard.accessor.impl.CompositeRecord;
55 import org.simantics.databoard.accessor.impl.DirectoryMap;
56 import org.simantics.databoard.accessor.impl.EventCollection;
57 import org.simantics.databoard.accessor.interestset.InterestSet;
58 import org.simantics.databoard.accessor.wire.WireClient;
59 import org.simantics.databoard.accessor.wire.WireServer;
60 import org.simantics.databoard.adapter.AdaptException;
61 import org.simantics.databoard.binding.ArrayBinding;
62 import org.simantics.databoard.binding.Binding;
63 import org.simantics.databoard.binding.BooleanBinding;
64 import org.simantics.databoard.binding.ByteBinding;
65 import org.simantics.databoard.binding.DoubleBinding;
66 import org.simantics.databoard.binding.FloatBinding;
67 import org.simantics.databoard.binding.IntegerBinding;
68 import org.simantics.databoard.binding.LongBinding;
69 import org.simantics.databoard.binding.MapBinding;
70 import org.simantics.databoard.binding.OptionalBinding;
71 import org.simantics.databoard.binding.RecordBinding;
72 import org.simantics.databoard.binding.StringBinding;
73 import org.simantics.databoard.binding.UnionBinding;
74 import org.simantics.databoard.binding.VariantBinding;
75 import org.simantics.databoard.binding.factory.BindingScheme;
76 import org.simantics.databoard.binding.factory.MutableBindingFactory;
77 import org.simantics.databoard.binding.impl.ObjectArrayBinding;
78 import org.simantics.databoard.binding.mutable.MutableVariant;
79 import org.simantics.databoard.binding.util.RandomValue;
80 import org.simantics.databoard.method.Client;
81 import org.simantics.databoard.method.Server;
82 import org.simantics.databoard.serialization.Serializer;
83 import org.simantics.databoard.type.Datatype;
84 import org.simantics.databoard.type.UnionType;
85 import org.simantics.databoard.util.binary.BinaryMemory;
86
87 /**
88  * o Set Value
89  * o Get Value
90  * o Listening
91  * o apply
92  * o Rollback
93  * 
94  * o Java Object
95  * o Memory Binary
96  * o File Binary
97  * 
98  * TODO Test {@link InvalidatedEvent}
99  *
100  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
101  */
102 public class TestAccessor {
103
104         RandomValue rv;
105         Map<Datatype, Binding> repository;
106         BindingScheme scheme;
107         /////////////////////////////////////
108         
109
110         public @Before void init() {
111                 rv = new RandomValue();
112                 repository = new HashMap<Datatype, Binding>();
113                 scheme = new MutableBindingFactory( repository );
114         }
115
116         public static File createTmpDir()
117         {
118                 String tmp = System.getenv("tmp");
119                 if (tmp==null) tmp = "c:/temp";
120                 Random r = new Random();
121                 String randomName = "tmp-"+(r.nextInt(10000)+10000);
122                 File tmpDir = new File(tmp+"/"+randomName);
123                 Boolean ok = tmpDir.mkdirs();
124                 assertTrue( ok );
125                 return tmpDir;
126         }       
127
128         public boolean isKeyShortEnough(Binding binding, Object value) throws AdaptException {
129                 String key = (String) Bindings.adapt(value, binding, Bindings.STR_VARIANT); 
130                 return key.length()<=200;
131         }
132
133         public @Test void testWireAccessor() throws Exception {
134                 System.out.println("Wire accessor test");
135                 
136                 // TODO: Fix this!
137                 if (true) return;
138
139                 for (int i=0; i<10000; i++) {
140                         Bindings.defaultBindingRepository.clear();
141                         Bindings.bindingRepository.clear();
142                         Bindings.serializerRepository.clear();
143                         repository.clear();
144                         System.out.println(i+": ");
145                         rv = new RandomValue(i); 
146                         rv.refereableRecords = false;
147                         Datatype type = rv.randomType(0, 3);
148                         Binding binding = scheme.getBindingUnchecked(type);
149                         Object instance = binding.accept(rv);
150 //                      System.out.println(binding.printValue(instance, true));
151                         Accessor accessor = Accessors.getAccessor(binding, instance);
152                         
153                         WireServer wireServer = new WireServer(accessor);
154                         Server server = new Server(0, wireServer.getMethodInterface());
155                         WireClient wireClient = new WireClient();
156                         Client client = new Client(InetAddress.getByName("localhost"), server.getPort(), wireClient.getClientMethodInterface());
157                         wireClient.setServerMethodInterface(client.getConnection().getRemoteMethodInterface());
158                         Accessor remoteAccessor = (Accessor) wireClient.getAccessor(null);
159                         testAccessor( remoteAccessor, false );
160                         
161                         wireClient.close();
162                         client.close();
163                         server.close();
164                 }
165                 
166         }
167                 
168         public @Test void testBinaryAccessor() throws Exception {
169                 System.out.println("Test Binary Memory:");
170                 
171                 Datatype type = Datatypes.VARIANT;
172                 Binding binding = scheme.getBindingUnchecked( type );
173                 Serializer s = binding.serializer();
174                 TObjectIntHashMap<Object> identities = new TObjectIntHashMap<Object>();
175                 
176                 for (int i=0; i<10000; i++) {
177                         Bindings.defaultBindingRepository.clear();
178                         Bindings.bindingRepository.clear();
179                         Bindings.serializerRepository.clear();                  
180                         repository.clear();                     
181                         rv = new RandomValue(i); 
182                         rv.getRandom().nextLong();
183                         rv.refereableRecords = false;
184                         System.out.println(i+": ");
185                         BinaryMemory ram = new BinaryMemory(0);
186                         Object instance = binding.accept(rv);
187                         
188                         binding.assertInstaceIsValid(instance);
189 //                      System.out.println(instance);
190                         
191                         identities.clear();
192                         int size = s.getSize(instance, identities);
193                         
194                         ram.setLength(size);                    
195                         ram.position(0);
196                         identities.clear();
197                         s.serialize(ram, identities, instance);
198                         identities.clear();
199
200                         ram.position(0L);
201                         Object instance2 = s.deserialize(ram);
202                         assertTrue( binding.equals(instance, instance2) );
203                         binding.assertInstaceIsValid(instance2);
204                         
205                         VariantAccessor a = (VariantAccessor) Accessors.getAccessor(ram, type);
206                         
207                         testAccessor(a);
208                         
209                 }
210                 
211         }
212
213         
214         public @Test void testJavaAccessor() throws Exception {
215                 System.out.println("Test Java Objects:");
216                 for (int i=0; i<10000; i++) {
217                         Bindings.defaultBindingRepository.clear();
218                         Bindings.bindingRepository.clear();
219                         Bindings.serializerRepository.clear();
220                         repository.clear();                     
221                         System.out.println(i+": ");
222                         rv = new RandomValue(i); 
223                         rv.refereableRecords = false;
224                         Datatype type = rv.randomType(0, 3);
225                         Binding binding = scheme.getBindingUnchecked(type);
226                         Object instance = binding.accept(rv);
227 //                      System.out.println(binding.printValue(instance, true));
228                         Accessor accessor = Accessors.getAccessor(binding, instance);
229                         testAccessor(accessor);
230                 }
231         }       
232
233         /**
234          * This test tests composite record by adding 10 fields, and running the 
235          * composition as a record accessor
236          */
237         public @Test void testCompositeRecord() throws Exception {
238                 System.out.println("Test composite accessor");
239                 for (int i=0; i<100; i++) {
240                         CompositeRecord record = new CompositeRecord();
241                         for (int j=1; j<=10; j++) {
242                                 
243                                 Binding binding = Bindings.MUTABLE_VARIANT;
244                                 rv = new RandomValue(i*543+j*23); 
245                                 rv.getRandom().nextLong();
246                                 rv.refereableRecords = false;   
247                                 MutableVariant instance = (MutableVariant) binding.accept(rv);
248                                 String fieldName = "Field"+j;
249                                 Accessor fa = Accessors.getAccessor(instance.getBinding(), instance.getValue());
250                                 record.addField(fieldName, fa);
251                         }
252                         System.out.println(i);
253                         
254                         testAccessor( record );
255                 }
256         }
257         
258         
259         public @Test void testFolderMap() throws Exception {
260                 // 1000 tests proves failure
261                 for (int i=0; i<100; i++) {
262                         Bindings.defaultBindingRepository.clear();
263                         Bindings.bindingRepository.clear();
264                         Bindings.serializerRepository.clear();
265                         repository.clear();
266                         
267                         System.out.println(i+": ");
268                         File dir = createTmpDir();
269                         DirectoryMap map = Accessors.openDirectory(dir);
270                         Binding keyBinding = Bindings.STR_VARIANT; 
271                         try {
272                                 System.out.println("Test Folder Map: "+dir);                    
273                                 
274                                 // Create 10 files
275                                 for (int j=0; j<10; j++) {
276                                         rv = new RandomValue(i*231231243+j*213); 
277                                         rv.refereableRecords = false;
278                                         
279                                         // Create Key                           
280                                         String key = "";
281                                         do {
282                                                 key = (String) keyBinding.accept(rv);
283                                         } while (key.length() > 240);
284                                         
285                                         // Create value 
286                                         Datatype valueType = rv.randomType(0, 2);                                       
287                                         Binding valueBinding = scheme.getBindingUnchecked(valueType);
288                                         Object value = valueBinding.accept(rv);                                 
289
290                                         System.out.println(key);
291                                         MutableVariant vv = new MutableVariant(valueBinding, value);
292                                         map.put(Bindings.STR_VARIANT, key, Bindings.MUTABLE_VARIANT, vv);
293                                 }
294                                 
295                                 // Test the map
296                                 testAccessor(map);
297                                 
298                         } finally {
299                                 // Remove all files in the folder
300                                 map.clear();
301                                 map.close();
302                                 System.out.println( dir.listFiles().length + " files.");
303                                 dir.delete();
304                         }
305                         
306                 }
307                 
308         }       
309         
310         public @Test void testBinaryFile() throws Exception {
311                 File tmpFile = File.createTempFile("TestAccessor", ".dat");
312                 System.out.println("Test Binary File: "+tmpFile);
313                 tmpFile.deleteOnExit();
314                 FileVariantAccessor fa = Accessors.createFile(tmpFile);         
315                 Datatype type = Datatypes.VARIANT;
316                 Binding binding = scheme.getBindingUnchecked( type );
317                 
318                 for (int i=0; i<10000; i++) {
319                         Bindings.bindingRepository.clear();
320                         Bindings.serializerRepository.clear();
321                         Bindings.defaultBindingRepository.clear();
322                         repository.clear();
323                         
324                         System.out.println(i+": ");
325                         rv = new RandomValue(i);                        
326                         rv.getRandom().nextLong();
327                         rv.refereableRecords = false;
328                         
329                         Object instance = binding.accept(rv);
330                         System.out.print(i+": "+ binding.printValueDefinition(instance, true));
331                         fa.setValue(binding, instance);
332                         testAccessor(fa);
333                 }
334                 fa.close();
335                 
336         }
337                 
338         
339         /////////////////////////////////////
340
341     public void testAccessor(Accessor a) throws Exception {
342         testAccessor(a, true);
343     }
344         
345         public void testAccessor(Accessor a, boolean runTypeSpecific) throws Exception {
346                 // Init
347                 Datatype type = a.type();
348                 Binding binding = scheme.getBindingUnchecked(type);
349                 InterestSet is = InterestSet.newInterestSet(type, true, true, true);
350                 boolean mutable = !binding.isImmutable();
351                 
352                 // Original value and test value
353                 Object origValue = a.getValue(binding);
354                 binding.assertInstaceIsValid(origValue);
355                 Object testValue = binding.accept(rv);
356
357                 // Test Accessor#getValue(binding, instance);
358                 Binding mutableBinding = Bindings.getMutableBinding(type);
359                 Object mutableInstance = mutableBinding.createDefault();
360                 a.getValue(mutableBinding, mutableInstance);
361                 assertTrue( Bindings.equals(binding, origValue, mutableBinding, mutableInstance) );
362                                 
363                 boolean same = binding.equals(origValue, testValue);
364                 // Create a reference value and an accessor
365                 Object refValue = binding.clone(origValue);
366                 Accessor ra = Accessors.getAccessor(binding, refValue);
367                 
368                 if ( mutable ) {
369         
370                         // Write test, without listeners
371                         ra.setValue(binding, testValue);
372                         Object refClone = ra.getValue(binding);
373                         assertTrue( binding.equals(testValue, refClone) );
374                         ra.setValue(binding, binding.clone(origValue) );
375                         refClone = ra.getValue(binding);
376                         assertTrue( binding.equals(origValue, refClone) );
377                         
378                         // Write test, with listeners
379                         ChangeSet cs = new ChangeSet();      // Collects Transformation form origValue to testValue
380                         a.addListener(cs, is, null, null);
381                         a.setValue(binding, testValue); 
382                         // There must be events in change set 
383                         if (!same) assertFalse(cs.isEmpty());
384                                         
385                         // Verify the accessor now contains the test value
386                         Object x = a.getValue(binding);
387                         assertTrue( binding.equals(testValue, x ) ); 
388                         
389                         // Convert reference value to testValue
390                         LinkedList<Event> rollback = new LinkedList<Event>();
391                         List<Event> events = cs.getAndClearEvents();  // Transformation form origValue to testValue
392                         ra.apply(events, rollback);         // Apply transformation from origValue to testValue, and gather rollback, a transformation from testValue to origValue
393                         x = ra.getValue(binding);
394                         assertTrue( binding.equals(x, testValue) );
395                         
396                         // Revert reference value to origValue using rollback
397                         a.removeListener(cs);
398                         a.apply(rollback, null);            // Apply transformation from testValue to origValue
399                         x = a.getValue(binding);
400                         assertTrue( binding.equals( x, origValue ) );
401                 }
402
403                 // Ensure the accessor has the correct value
404                 Object x = a.getValue(binding);
405                 assertTrue( binding.equals( x, origValue) );
406                 
407                 if (runTypeSpecific) {
408                 // Type specific tests
409                 if (a instanceof ArrayAccessor) testArrayAccessor((ArrayAccessor) a); 
410                 if (a instanceof RecordAccessor) testRecordAccessor((RecordAccessor) a); 
411                 if (a instanceof MapAccessor) testMapAccessor((MapAccessor) a); 
412                 if (a instanceof BooleanAccessor) testBooleanAccessor((BooleanAccessor) a); 
413                 if (a instanceof ByteAccessor) testByteAccessor((ByteAccessor) a); 
414                 if (a instanceof DoubleAccessor) testDoubleAccessor((DoubleAccessor) a); 
415                 if (a instanceof FloatAccessor) testFloatAccessor((FloatAccessor) a); 
416                 if (a instanceof IntegerAccessor) testIntegerAccessor((IntegerAccessor) a); 
417                 if (a instanceof LongAccessor) testLongAccessor((LongAccessor) a); 
418                 if (a instanceof OptionalAccessor) testOptionalAccessor((OptionalAccessor) a); 
419                 if (a instanceof StringAccessor) testStringAccessor((StringAccessor) a); 
420                 if (a instanceof UnionAccessor) testUnionAccessor((UnionAccessor) a); 
421                 if (a instanceof VariantAccessor) testVariantAccessor((VariantAccessor) a);
422         
423                 // Ensure the accessor has the correct value
424                 a.setValue(binding, origValue);                 
425                 x = a.getValue(binding);
426                 assertTrue( binding.equals( x, origValue) );
427                 }               
428         }
429         
430         public void testMapAccessor(MapAccessor a) throws Exception {
431                 Datatype type = a.type();
432                 MapBinding binding = (MapBinding) scheme.getBindingUnchecked(type);
433                 Binding kb = binding.getKeyBinding();
434                 Binding vb = binding.getValueBinding();
435                 InterestSet is = InterestSet.newInterestSet(type, true, true, false);
436                 boolean mutable = !binding.isImmutable();
437                 int len = a.size();
438                 
439                 // getAll(Binding, Binding, Object[], Object[])
440                 Object oks[] = new Object[ len ];
441                 Object ovs[] = new Object[ len ];
442                 a.getAll(kb, vb, oks, ovs);
443
444                 // getAll(Binding, Binding, Map<Object, Object>)
445                 TreeMap<Object, Object> om = new TreeMap<Object, Object>(kb);
446                 a.getAll(kb, vb, om);
447
448                 // getKeys(Binding), getValues(Binding)
449                 Object oks2[] = a.getKeys(kb);
450                 Object ovs2[] = a.getValues(vb);                
451                 
452                 // assert the results are the same for the getAll()s and getKeys and getValues 
453                 for (int i=0; i<len; i++) {
454                         assertTrue( om.containsKey(oks[i]) );
455                         assertTrue( om.containsKey(oks2[i]) );
456                         Object v = om.get(oks[i]);
457                         assertTrue( vb.equals( v, ovs[i] ) );
458                         assertTrue( vb.equals( v, ovs2[i] ) );
459                         v = om.get(oks2[i]);
460                         assertTrue( vb.equals( v, ovs[i] ) );
461                         assertTrue( vb.equals( v, ovs2[i] ) );
462                 }
463
464                 // Test Get entries
465                 if (len>2) {
466                         // Get all
467                         try {
468                     Object keys[] = new Object[ len ];
469                     Object values[] = new Object[ len ];
470                         int c = a.getEntries(kb, a.getFirstKey(kb), true, a.getLastKey(kb), true, 
471                                 new ObjectArrayBinding(kb), keys, 
472                                 new ObjectArrayBinding(vb), values, -1);
473     
474                         assertEquals(len, c);
475                         for (int i=0; i<len; i++) {                             
476                                 assertTrue( kb.equals( oks[i], keys[i] ) );
477                                 assertTrue( vb.equals( ovs[i], values[i] ) );
478                         }
479                         
480                         // Exclude first and last
481                         keys = new Object[ len-2 ];
482                         values = new Object[ len-2 ];
483                         c = a.getEntries(kb, a.getFirstKey(kb), false, a.getLastKey(kb), false, 
484                                         new ObjectArrayBinding(kb), keys, 
485                                         new ObjectArrayBinding(vb), values, -1);
486                         assertEquals(len-2, c);
487                         for (int i=1; i<len-1; i++) {                           
488                                 assertTrue( kb.equals( oks[i], keys[i-1] ) );
489                                 assertTrue( vb.equals( ovs[i], values[i-1] ) );
490                         }
491         
492                         // Get one
493                         c = a.getEntries(kb, a.getFirstKey(kb), true, a.getLastKey(kb), false, 
494                                         new ObjectArrayBinding(kb), keys, 
495                                         new ObjectArrayBinding(vb), values, 1);
496                         assertEquals(1, c);
497                         assertTrue( kb.equals( oks[0], keys[0] ) );
498                         assertTrue( vb.equals( ovs[0], values[0] ) );
499                         }
500                         catch (AccessorException e) {
501                             assertEquals( "Not implemented", e.getMessage() );
502                         }
503                         
504                 }
505                 
506                 // Create test values
507                 TreeSet<Object> keys = new TreeSet<Object>(kb);
508                 for (int i=0; i<10; i++) {
509                         Object key = null;
510                         if (kb.type().equals(Datatypes.VARIANT)) {
511                                 do {
512                                         key = kb.accept(rv);
513                                 } while( !kb.type().equals(Datatypes.VARIANT) || !isKeyShortEnough(kb, key) );                  
514                         } else {
515                                 key = kb.accept(rv);                            
516                         }
517                         keys.add( key );
518                 }
519                 int testValueCount = keys.size();
520                 Object tks[] = keys.toArray( new Object[testValueCount] );
521                 Object tvs[] = new Object[ testValueCount ];
522                 for (int i=0; i<testValueCount; i++) tvs[i] = vb.accept(rv);
523
524                 if (len>=3) {
525                         // getFirstKey(Binding)
526                         Object fk = a.getFirstKey(kb);
527                         assertTrue( kb.equals(fk, oks[0]) );
528
529                         // getLastKey(Binding)
530                         Object lk = a.getLastKey(kb);
531                         assertTrue( kb.equals(lk, oks[len-1]) );
532                         
533                         // getLowerKey(Binding, Object)
534                         Object k = a.getLowerKey(kb, fk);
535                         assertNull(k);                  
536                         k = a.getLowerKey(kb, lk);
537                         assertTrue( kb.equals(k, oks[len-2]) );  
538                         
539                         // getFloorKey(Binding, Object)
540                         k = a.getFloorKey(kb, fk);
541                         assertTrue( kb.equals(k, oks[0]) );  
542                         k = a.getFloorKey(kb, lk);
543                         assertTrue( kb.equals(k, oks[len-1]) );  
544                         
545                         // getCeilingKey(Binding, Object)
546                         k = a.getCeilingKey(kb, lk);
547                         assertTrue( kb.equals(k, oks[len-1]) );  
548                         k = a.getCeilingKey(kb, fk);
549                         assertTrue( kb.equals(k, oks[0]) );  
550                         
551                         // getHigherKey(Binding, Object)
552                         k = a.getHigherKey(kb, lk);
553                         assertNull(k);                  
554                         k = a.getHigherKey(kb, fk);
555                         assertTrue( kb.equals(k, oks[1]) );  
556                 }
557
558                 // clear
559                 // putAll(Binding, Binding, Object[], Object[])
560                 a.clear();
561                 int size = a.size();
562                 assertEquals( 0, size );
563                 a.putAll(kb, vb, oks, ovs);
564                 size = a.size();                
565                 assertEquals( len, size );
566                 
567                 // clear
568                 // putAll(Binding, Binding, Map<Object, Object>)
569                 a.clear();
570                 assertEquals( 0, a.size() );
571                 a.putAll(kb, vb, om);
572                 assertEquals( len, a.size() );
573                 
574                 // containsKey
575                 // containsValue
576                 for (int i=0; i<len; i++) {
577                         assertTrue( a.containsKey(kb, oks[i]) );
578                         assertTrue( a.containsValue(vb, ovs[i]) );
579                 }
580                                 
581                 // Add, Remove
582                 if ( mutable ) {
583                         // put (insert)
584                         int count = len;
585                         for (int i=0; i<testValueCount; i++) {
586                                 if (!a.containsKey(kb, tks[i])) count++;
587                                 a.put(kb, tks[i], vb, tvs[i]);
588                         }
589                         assertEquals(count, a.size());
590                         for (int i=0; i<testValueCount; i++) {
591                                 Object o = a.get(kb, tks[i], vb);
592                                 assertTrue( vb.equals(tvs[i], o) );
593                         }
594                         // remove(Binding, Object)
595                         for (int i=0; i<testValueCount; i++) {
596                                 a.remove(kb, tks[i]);
597                         }
598                         for (int i=0; i<len; i++) {
599                                 a.remove(kb, oks[i]);
600                         }                       
601                         a.putAll(kb, vb, oks, ovs);
602                 }
603                 
604                 // Set
605                 int common = Math.min(len, testValueCount);
606                 
607                 for (int i=0; i<common; i++) {
608                         a.put(kb, oks[i], vb, tvs[i]);
609                         Object x = a.get(kb, oks[i], vb);
610                         assertTrue( vb.equals( tvs[i], x) );                    
611                 }
612                 for (int i=0; i<common; i++) {
613                         a.put(kb, oks[i], vb, ovs[i]);
614                         Object x = a.get(kb, oks[i], vb);
615                         assertTrue( vb.equals( ovs[i], x ) );                   
616                 }
617                 
618                 //// Test sub-accessors with recursion
619                 for (int i=0; i<len; i++) {
620                         Accessor sa = a.getValueAccessor(kb, oks[i]);
621                         testAccessor(sa);
622                 }                       
623         }
624         
625         public void testArrayAccessor(ArrayAccessor a) throws Exception {
626                 Datatype type = a.type();
627                 ArrayBinding binding = (ArrayBinding) scheme.getBindingUnchecked(type);
628                 Binding cb = binding.getComponentBinding();
629                 InterestSet is = InterestSet.newInterestSet(type, true, true, false);
630                 boolean mutable = !binding.isImmutable();
631
632                 int len = a.size();
633                 Object ovs[] = new Object[ len ];
634                 a.getAll(cb, ovs);
635
636                 //// Create test values
637                 int testValueCount = rv.getRandom().nextInt(10)+10;
638                 Object tvs[] = new Object[ testValueCount ];
639                 Object tvs2[] = new Object[ testValueCount ];
640                 for (int i=0; i<testValueCount; i++) {
641                         tvs[i] = cb.accept(rv);
642                         tvs2[i] = cb.accept(rv);                                
643                 }                       
644                 
645                 // Add, Remove
646                 if ( mutable ) {
647                         
648                         //// Add in values to end
649                         a.addAll(cb, tvs);                      
650                         // Test get 
651                         for (int i=0; i<testValueCount; i++) {
652                                 Object o1 = a.get(i + len, cb);
653                                 Object o2 = tvs[i];
654                                 assertTrue( cb.equals(o1, o2) );
655                         }
656                         
657                         // Test get to existing instance
658                         {
659                                 Object o1 = cb.createDefault();
660                                 for (int i=0; i<testValueCount; i++) {
661                                         a.get(i + len, cb, o1);
662                                         Object o2 = tvs[i];
663                                         assertTrue( cb.equals(o1, o2) );
664                                 }
665                         }
666
667                         // Test getAll
668                         Object all[] = new Object[ testValueCount + len ];
669                         a.getAll(cb, all);
670                         for (int i=0; i<testValueCount; i++) {
671                                 Object o1 = all[i+len];
672                                 Object o2 = tvs[i];
673                                 assertTrue( cb.equals(o1, o2) );
674                         }                       
675                         a.remove(len, testValueCount);
676                         for (int i=0; i<len; i++) {
677                                 Object o1 = ovs[i];
678                                 Object o2 = a.get(i, cb);
679                                 assertTrue( cb.equals(o1, o2) );
680                         }                                               
681                         assertEquals(len, a.size());
682                         
683                         
684                         //// Add in values to the beginning
685                         a.addAll(0, cb, tvs);
686                         for (int i=0; i<testValueCount; i++) {
687                                 Object o1 = a.get(i, cb);
688                                 Object o2 = tvs[i];
689                                 assertTrue( cb.equals(o1, o2) );
690                         }
691                         // Test getAll
692                         a.getAll(cb, all);
693                         for (int i=0; i<testValueCount; i++) {
694                                 Object o1 = all[i];
695                                 Object o2 = tvs[i];
696                                 assertTrue( cb.equals(o1, o2) );
697                         }                       
698                         a.remove(0, testValueCount);
699                         assertEquals(len, a.size());
700                 }
701                 
702                 int oldSize = a.size();
703                 a.setSize( oldSize + 10);
704                 assertEquals( oldSize+10, a.size() );
705                 a.setSize( oldSize );
706                 assertEquals( oldSize, a.size() );
707
708                 //// Test setValue()
709                 int common = Math.min(len, testValueCount);
710                 for (int i=0; i<common; i++) 
711                         a.set(i, cb, tvs[i]);
712                 
713                 for (int i=0; i<common; i++) assertTrue( cb.equals( tvs[i], a.get(i, cb)) );
714                 for (int i=0; i<common; i++) a.set(i, cb, ovs[i]);              
715                 for (int i=0; i<common; i++) assertTrue( cb.equals( ovs[i], a.get(i, cb)) );
716                 
717                 //// Test sub-accessors with recursion
718                 for (int i=0; i<len; i++) {
719                         Accessor sa = a.getAccessor(i);
720                         testAccessor(sa);
721                 }               
722                 
723         }
724         
725         public void testRecordAccessor(RecordAccessor a) throws Exception {
726                 Datatype type = a.type();
727                 RecordBinding binding = (RecordBinding) scheme.getBindingUnchecked(type);
728                 Binding cbs[] = binding.getComponentBindings();
729                 InterestSet is = InterestSet.newInterestSet(type, true, true, false);
730
731                 int len = a.count();
732                 Object ovs[] = new Object[ len ];
733                 for (int i=0; i<len; i++) ovs[i] = a.getFieldValue(i, cbs[i]);
734
735                 //// Create test values
736                 Object tvs[] = new Object[ len ];
737                 Object tvs2[] = new Object[ len ];
738                 for (int i=0; i<len; i++) {
739                         tvs[i] = cbs[i].accept(rv);
740                         tvs2[i] = cbs[i].accept(rv);                            
741                 }                       
742
743                 //// Test setValue()
744 //              System.gc();
745                 for (int i=0; i<len; i++) 
746                         a.setFieldValue(i, cbs[i], tvs[i]);
747                 for (int i=0; i<len; i++) assertTrue( cbs[i].equals( tvs[i], a.getFieldValue(i, cbs[i])) );
748                 for (int i=0; i<len; i++) a.setFieldValue(i, cbs[i], ovs[i]);           
749                 for (int i=0; i<len; i++) assertTrue( cbs[i].equals( ovs[i], a.getFieldValue(i, cbs[i])) );
750                 
751                 //// Test sub-accessors with recursion
752                 for (int i=0; i<len; i++) {
753                         Accessor sa = a.getFieldAccessor(i);
754                         testAccessor(sa);
755                 }               
756                 
757         }
758         
759         public void testOptionalAccessor(OptionalAccessor a) throws Exception {
760                 Datatype type = a.type();
761                 OptionalBinding binding = (OptionalBinding) scheme.getBindingUnchecked(type);
762                 Binding cb = binding.getComponentBinding();
763                 InterestSet is = InterestSet.newInterestSet(type, true, true, true);
764                 
765                 // Remember original value
766                 boolean hadValue = a.hasValue();
767                 Object ov = hadValue ? a.getComponentValue(cb) : null;          
768                 Object tv = cb.accept(rv);
769
770                 a.setComponentValue(cb, tv);
771                 assertTrue( cb.equals(a.getComponentValue(cb), tv) );
772                 assertEquals( true, a.hasValue());
773                 
774                 a.setNoValue();
775                 assertEquals( false, a.hasValue());
776
777                 // Test Invalidated Event
778                 {                       
779                         a.setNoValue();
780                         a.setComponentValue(cb, tv);
781                         Accessor sa = a.getComponentAccessor();
782                         EventCollection ec = new EventCollection();
783                         a.addListener(ec, is, null, null);
784                         a.setNoValue();         
785                         a.removeListener(ec);
786                         boolean invalidatedEventOk = false;
787                         for (Event e : ec.getAndClearEvents()) {
788                                 invalidatedEventOk |= (e instanceof InvalidatedEvent) && (e.reference !=null);
789                         }
790                         sa.getClass();
791                         assertTrue( invalidatedEventOk );                               
792                 }
793                 
794                 // Restore value
795                 if (hadValue) {
796                         a.setComponentValue(cb, ov);
797                 } else {
798                         a.setNoValue();
799                 }
800         }
801         
802         public void testUnionAccessor(UnionAccessor a) throws Exception {
803                 UnionType type = a.type();
804                 UnionBinding binding = (UnionBinding) scheme.getBindingUnchecked(type);
805                 Binding cbs[] = binding.getComponentBindings();
806                 InterestSet is = InterestSet.newInterestSet(type, true, true, true);
807                 int len = a.count();
808
809                 // Get original values
810                 int ot = a.getTag();
811                 Object ov = a.getComponentValue(cbs[ot]);
812                 
813                 //// Create test values
814                 Object tvs[] = new Object[ len ];
815                 Object tvs2[] = new Object[ len ];
816                 for (int i=0; i<len; i++) {
817                         tvs[i] = cbs[i].accept(rv);
818                         tvs2[i] = cbs[i].accept(rv);                            
819                 }                       
820
821                 //// Test setValue()
822                 for (int i=0; i<len; i++) {
823                         a.setComponentValue(i, cbs[i], tvs[i]);
824                         assertEquals( i, a.getTag() );
825                         assertTrue( Bindings.equals(cbs[i], a.getComponentValue(cbs[i]), cbs[i], tvs[i]) );
826                 }
827                 
828                 // Test Invalidated Event
829                 if (type.getComponentCount()>1)
830                 {
831                         int i=0;
832                         a.setComponentValue(i, cbs[i], tvs[i]);
833                         Accessor sa = a.getComponentAccessor();
834                         EventCollection ec = new EventCollection();
835                         a.addListener(ec, is, null, null);
836                         i = 1;
837                         a.setComponentValue(i, cbs[i], tvs[i]);
838                         boolean invalidatedEventOk = false;
839                         List<Event> events = ec.getAndClearEvents();
840                         for (Event e : events) {
841                                 invalidatedEventOk |= (e instanceof InvalidatedEvent) && (e.reference !=null);
842                         }
843                         a.removeListener(ec);
844                         sa.getClass();
845                         assertTrue( invalidatedEventOk );                               
846                 }
847                 
848                 a.setComponentValue(ot, cbs[ot], ov);
849                 
850                 //// Test sub-accessors with recursion
851                 Accessor sa = a.getComponentAccessor();
852                 testAccessor(sa);
853                 
854         }
855         
856         public void testVariantAccessor(VariantAccessor a) throws Exception {
857                 Datatype type = a.type();
858                 VariantBinding binding = (VariantBinding) scheme.getBindingUnchecked(type);
859                 InterestSet is = InterestSet.newInterestSet(type, true, true, true);
860                 
861                 // Remember the original value 
862                 Binding ob = scheme.getBindingUnchecked( type );
863                 Object ov = a.getValue(ob);
864                 ob.assertInstaceIsValid(ov);
865                 boolean mutable = !binding.isImmutable();
866                 
867                 if (mutable) {
868                         // Create test values
869                         int testValueCount = 10;
870                         Binding tvb[] = new Binding[testValueCount];
871                         Object tvs[] = new Object[testValueCount];
872                         for (int i=0; i<testValueCount; i++) {
873                                 tvb[i] = scheme.getBindingUnchecked( rv.randomType(0, 2) );
874                                 tvs[i] = tvb[i].accept(rv);
875                         }
876                 
877                         // Set & Get
878                         for (int i=0; i<testValueCount; i++) {
879                                 a.setContentValue(tvb[i], tvs[i]);                              
880                                 Object o = a.getContentValue(tvb[i]);
881                                 assertTrue( tvb[i].equals(o, tvs[i]) );
882                         }
883                         
884                         // Test Invalidated Event
885                         {
886                                 Binding tb = tvb[1];
887                                 Object tv = tvs[1];
888                                 Datatype ct = tvb[0].type();
889                                 a.setContentValue(tvb[0], tvs[0]);                                      
890                                 EventCollection ec = new EventCollection();
891                                 a.addListener(ec, is, null, null);
892                                 Accessor sa = a.getContentAccessor();
893                                 a.setContentValue(tvb[1], tvs[1]);                                      
894                                 a.removeListener(ec);
895                                 
896                                 // Assigned same type
897                                 if (ct.getClass().equals(tb.type().getClass())) {
898                                         
899                                 } else {                                
900                                         boolean invalidatedEventOk = false;
901                                         List<Event> events = ec.getAndClearEvents();                            
902                                         for (Event e : events) {
903                                                 invalidatedEventOk |= (e instanceof InvalidatedEvent) && (e.reference !=null);
904                                         }
905                                         assertTrue( invalidatedEventOk );
906                                 }
907                         }                       
908                 }
909                 
910                 //// Test sub-accessors with recursion
911                 Accessor sa = a.getContentAccessor();
912                 testAccessor(sa);
913                 
914                 // Restore
915                 a.setValue(ob, ov);             
916         }
917         
918         public void testByteAccessor(ByteAccessor a) throws Exception {
919                 byte ov = a.getValue();
920                 ByteBinding b = Bindings.BYTE;
921                 for (int i=0; i<10; i++) {
922                         Byte r = (Byte) rv.visit(b);            
923                         a.setValue(r);
924                         assertTrue( r == a.getValue() );
925                 }
926                 a.setValue(ov);                 
927         }
928         
929         public void testDoubleAccessor(DoubleAccessor a) throws Exception {
930                 double ov = a.getValue();
931                 DoubleBinding b = Bindings.DOUBLE;
932                 for (int i=0; i<10; i++) {
933                         Double r = (Double) rv.visit(b);                
934                         a.setValue(r);
935                         assertTrue( r == a.getValue() );
936                 }
937                 a.setValue(ov);                 
938         }
939         
940         public void testFloatAccessor(FloatAccessor a) throws Exception {
941                 float ov = a.getValue();
942                 FloatBinding b = Bindings.FLOAT;
943                 for (int i=0; i<10; i++) {
944                         Float r = (Float) rv.visit(b);          
945                         a.setValue(r);
946                         assertTrue( r == a.getValue() );
947                 }
948                 a.setValue(ov);                 
949         }
950         
951         public void testIntegerAccessor(IntegerAccessor a) throws Exception {
952                 int ov = a.getValue();
953                 IntegerBinding b = Bindings.INTEGER;
954                 for (int i=0; i<10; i++) {
955                         Integer r = (Integer) rv.visit(b);              
956                         a.setValue(r);
957                         assertTrue( r == a.getValue() );
958                 }
959                 a.setValue(ov);                 
960         }
961         
962         public void testLongAccessor(LongAccessor a) throws Exception {
963                 long ov = a.getValue();
964                 LongBinding b = Bindings.LONG;
965                 for (int i=0; i<10; i++) {
966                         Long r = (Long) rv.visit(b);            
967                         a.setValue(r);
968                         assertTrue( r == a.getValue() );
969                 }
970                 a.setValue(ov);                 
971         }
972                 
973         public void testStringAccessor(StringAccessor a) throws Exception {
974                 String ov = a.getValue();
975                 StringBinding b = Bindings.STRING;
976                 for (int i=0; i<10; i++) {
977                         String r = (String) rv.visit(b);                
978                         a.setValue(r);
979                         assertEquals( r, a.getValue() );
980                 }
981                 a.setValue(ov);                 
982         }
983         
984         public void testBooleanAccessor(BooleanAccessor a) throws Exception {
985                 Boolean ov = a.getValue();
986                 BooleanBinding b = Bindings.BOOLEAN;
987                 for (int i=0; i<10; i++) {
988                         Boolean r = (Boolean) rv.visit(b);              
989                         a.setValue(r);
990                         assertEquals( r, a.getValue() );
991                 }
992                 a.setValue(ov); 
993         }
994                 
995         
996 }
997