1 /*
   2  * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.css;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Iterator;
  30 import java.util.List;
  31 import java.util.Set;
  32 
  33 import javafx.beans.value.ChangeListener;
  34 import javafx.collections.ObservableSet;
  35 import javafx.collections.SetChangeListener;
  36 import javafx.css.PseudoClass;
  37 import static org.junit.Assert.*;
  38 import org.junit.Before;
  39 import org.junit.Test;
  40 
  41 /**
  42  *
  43  * @author dgrieve
  44  */
  45 public class PseudoClassTest {
  46     
  47     public PseudoClassTest() {
  48     }
  49 
  50     @Before
  51     public void before() {
  52         PseudoClassState.pseudoClassMap.clear();        
  53         PseudoClassState.pseudoClasses.clear();       
  54     }
  55     
  56     @Test
  57     public void testGetState() {
  58         String pseudoClass = "xyzzy";
  59         PseudoClass result = PseudoClass.getPseudoClass(pseudoClass);
  60         assertEquals(pseudoClass, result.getPseudoClassName());
  61     }
  62 
  63     @Test
  64     public void testCreateStatesInstance() {
  65         PseudoClassState result = new PseudoClassState();
  66         assertNotNull(result);
  67     }
  68 
  69     @Test
  70     public void testGetStateThrowsIllegalArgumentExceptionWithNullArg() {
  71         try {
  72             PseudoClass state = PseudoClass.getPseudoClass(null);
  73             fail();
  74         } catch (IllegalArgumentException exception) {
  75         }
  76     }
  77     
  78     @Test
  79     public void testGetStateThrowsIllegalArgumentExceptionWithEmptyArg() {
  80         try {
  81             PseudoClass state = PseudoClass.getPseudoClass(" ");
  82             fail();
  83         } catch (IllegalArgumentException exception) {
  84         }
  85     }
  86     
  87     @Test
  88     public void testState_getPseudoClass() {
  89         // no different than testing the getPseudoClassName method!
  90         String pseudoClass = "xyzzy";
  91         PseudoClass result = PseudoClass.getPseudoClass(pseudoClass);
  92         assertEquals(pseudoClass, result.getPseudoClassName());        
  93     }
  94 
  95     @Test
  96     public void testState_toString() {
  97         String pseudoClass = "xyzzy";
  98         PseudoClass result = PseudoClass.getPseudoClass(pseudoClass);
  99         assertEquals(pseudoClass, result.toString());        
 100     }
 101 
 102     @Test
 103     public void testPseudoClassState_add() {
 104         String pseudoClass = "xyzzy";
 105         PseudoClass state = PseudoClass.getPseudoClass(pseudoClass);
 106         PseudoClassState states = new PseudoClassState();
 107         states.add(state);
 108         
 109         List<PseudoClass> stateList = new ArrayList<PseudoClass>();
 110         Iterator<PseudoClass> iter = states.iterator();
 111         while (iter.hasNext()) {
 112             stateList.add(iter.next());
 113         }
 114         
 115         assertTrue(stateList.contains(state));
 116     }
 117 
 118     @Test
 119     public void testPseudoClassState_add_multipleStates() {
 120         String[] pseudoClasses = new String[] {
 121             "one", "two", "three", "four", "five"
 122         };
 123         
 124         PseudoClassState states = new PseudoClassState();
 125         
 126         for (int n=0; n<pseudoClasses.length; n++) {
 127             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 128             states.add(state);
 129         }
 130         
 131         List<PseudoClass> stateList = new ArrayList<PseudoClass>();
 132         Iterator<PseudoClass> iter = states.iterator();
 133         while (iter.hasNext()) {
 134             stateList.add(iter.next());
 135         }
 136 
 137         for (int n=0; n<pseudoClasses.length; n++) {
 138             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 139             assertTrue(stateList.contains(state));
 140         }
 141         
 142     }
 143     
 144     @Test
 145     public void testPseudoClassState_contains() {
 146         String[] pseudoClasses = new String[] {
 147             "one", "two", "three", "four", "five"
 148         };
 149         
 150         PseudoClassState states = new PseudoClassState();
 151         
 152         for (int n=0; n<pseudoClasses.length; n++) {
 153             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 154             states.add(state);
 155         }
 156         
 157         for (int n=0; n<pseudoClasses.length; n++) {
 158             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 159             assertTrue(states.contains(state));
 160         }
 161         
 162     }
 163     
 164     @Test
 165     public void testPseudoClassState_contains_negativeTest() {
 166         String[] pseudoClasses = new String[] {
 167             "one", "two", "three", "four", "five"
 168         };
 169         
 170         String[] notExpected = new String[] {
 171             "six", "seven", "eight"
 172         };
 173         
 174         PseudoClassState states = new PseudoClassState();
 175         
 176         for (int n=0; n<pseudoClasses.length; n++) {
 177             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 178             states.add(state);
 179         }
 180         
 181         for (int n=0; n<notExpected.length; n++) {
 182             PseudoClass state = PseudoClass.getPseudoClass(notExpected[n]);
 183             assertTrue(states.contains(state) == false);
 184         }
 185         
 186     }
 187 
 188     @Test
 189     public void testPseudoClassState_contains_null() {
 190         String[] pseudoClasses = new String[] {
 191             "one", "two", "three", "four", "five"
 192         };
 193         
 194         PseudoClassState states = new PseudoClassState();
 195         
 196         for (int n=0; n<pseudoClasses.length; n++) {
 197             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 198             states.add(state);
 199         }
 200         
 201         assertTrue(states.contains(null) == false);
 202         
 203     }
 204     
 205     @Test
 206     public void testPseudoClassState_removeState() {
 207         String[] pseudoClasses = new String[] {
 208             "one", "two", "three", "four", "five"
 209         };
 210 
 211         String[] expected = new String[] {
 212             "one", "two", "four", "five"
 213         };
 214         
 215         PseudoClassState states = new PseudoClassState();
 216         
 217         for (int n=0; n<pseudoClasses.length; n++) {
 218             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 219             states.add(state);
 220         }
 221         
 222         states.remove(PseudoClass.getPseudoClass("three"));
 223         
 224         assertTrue(states.contains(PseudoClass.getPseudoClass("three"))==false);
 225         
 226         // should still have the others.
 227         for (int n=1; n<expected.length; n++) {
 228             PseudoClass state = PseudoClass.getPseudoClass(expected[n]);
 229             assertTrue(states.contains(state));
 230         }
 231         
 232     }
 233 
 234     @Test
 235     public void testPseudoClassState_containsAll() {
 236         
 237         String[] setA = new String[] {
 238             "zero", "one"
 239         };
 240         
 241         PseudoClassState aStates = new PseudoClassState();
 242         for(int n=0; n<setA.length; n++) {
 243             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 244         }
 245         
 246         String[] setB = new String[] {
 247             "zero", "one", "two", "three"            
 248         };
 249         PseudoClassState bStates = new PseudoClassState();
 250         for(int n=0; n<setB.length; n++) {
 251             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 252         }
 253                         
 254         assertTrue(bStates.containsAll(aStates));
 255     }    
 256 
 257     @Test
 258     public void testPseudoClassState_containsAll_negativeTest() {
 259         
 260         String[] setA = new String[] {
 261             "zero", "one", "two", "three" 
 262         };
 263         
 264         PseudoClassState aStates = new PseudoClassState();
 265         for(int n=0; n<setA.length; n++) {
 266             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 267         }
 268         
 269         String[] setB = new String[] {
 270             "zero", "one"            
 271         };
 272         PseudoClassState bStates = new PseudoClassState();
 273         for(int n=0; n<setB.length; n++) {
 274             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 275         }
 276                         
 277         assertTrue(bStates.containsAll(aStates) == false);
 278     }    
 279 
 280     @Test
 281     public void testPseudoClassState_containsAll_whenSetsAreEqual() {
 282         
 283         String[] setA = new String[] {
 284             "zero", "one", "two", "three" 
 285         };
 286         
 287         PseudoClassState aStates = new PseudoClassState();
 288         for(int n=0; n<setA.length; n++) {
 289             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 290         }
 291         
 292         String[] setB = new String[] {
 293             "zero", "one", "two", "three"            
 294         };
 295         PseudoClassState bStates = new PseudoClassState();
 296         for(int n=0; n<setB.length; n++) {
 297             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 298         }
 299                         
 300         assertTrue(bStates.containsAll(aStates));
 301     }    
 302 
 303     @Test
 304     public void testPseudoClassState_containsAll_whenSetsDisjoint() {
 305         
 306         String[] setA = new String[] {
 307             "zero", "one", "two", "three" 
 308         };
 309         
 310         PseudoClassState aStates = new PseudoClassState();
 311         for(int n=0; n<setA.length; n++) {
 312             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 313         }
 314         
 315         String[] setB = new String[] {
 316             "four", "five", "six", "seven"            
 317         };
 318         PseudoClassState bStates = new PseudoClassState();
 319         for(int n=0; n<setB.length; n++) {
 320             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 321         }
 322                         
 323         assertTrue(bStates.containsAll(aStates) == false);
 324     }
 325 
 326     @Test
 327     public void testPseudoClassState_containsAll_whenOneSetEmpty() {
 328 
 329         String[] setA = new String[] {
 330                 "zero", "one", "two", "three"
 331         };
 332 
 333         PseudoClassState aStates = new PseudoClassState();
 334         for(int n=0; n<setA.length; n++) {
 335             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 336         }
 337 
 338         PseudoClassState bStates = new PseudoClassState();
 339 
 340         assertTrue(bStates.containsAll(aStates) == false);
 341         assertTrue(aStates.containsAll(bStates));
 342 
 343     }
 344 
 345     @Test
 346     public void testPseudoClassState_containsAll_whenBothSetsEmpty() {
 347 
 348         PseudoClassState aStates = new PseudoClassState();
 349         PseudoClassState bStates = new PseudoClassState();
 350 
 351         assertTrue(bStates.containsAll(aStates));
 352         assertTrue(aStates.containsAll(bStates));
 353 
 354     }
 355 
 356     @Test
 357     public void testPseudoClassState_size() {
 358         
 359         String[] pseudoClasses = new String[] {
 360             "one", "two", "three", "four", "five"
 361         };
 362 
 363         int expected = 5;
 364         
 365         PseudoClassState states = new PseudoClassState();
 366         
 367         for (int n=0; n<pseudoClasses.length; n++) {
 368             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 369             states.add(state);
 370         }
 371         
 372         assertEquals(expected, states.size());
 373     }
 374     
 375     @Test
 376     public void testPseudoClassState_size_afterRemove() {
 377         
 378         String[] pseudoClasses = new String[] {
 379             "one", "two", "three", "four", "five"
 380         };
 381 
 382         int expected = 4;
 383         
 384         PseudoClassState states = new PseudoClassState();
 385         
 386         for (int n=0; n<pseudoClasses.length; n++) {
 387             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 388             states.add(state);
 389         }
 390         
 391         states.remove(PseudoClass.getPseudoClass("three"));
 392         
 393         assertEquals(expected, states.size());
 394     }
 395 
 396     @Test
 397     public void testPseudoClassState_size_afterRemoveOnEmpty() {
 398         
 399         String[] pseudoClasses = new String[] {
 400             "one", "two", "three", "four", "five"
 401         };
 402 
 403         int expected = 0;
 404         
 405         PseudoClassState states = new PseudoClassState();
 406         
 407         for (int n=0; n<pseudoClasses.length; n++) {
 408             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 409             states.add(state);
 410         }
 411         
 412         for (int n=0; n<pseudoClasses.length; n++) {
 413             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 414             states.remove(state);
 415         }
 416         
 417         assertEquals(expected, states.size());
 418     }
 419 
 420     @Test
 421     public void testPseudoClassState_size_afterAddWhenAlreadyContains() {
 422         
 423         String[] pseudoClasses = new String[] {
 424             "one", "two", "three", "four", "five"
 425         };
 426 
 427         int expected = 5;
 428         
 429         PseudoClassState states = new PseudoClassState();
 430         
 431         for (int n=0; n<pseudoClasses.length; n++) {
 432             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 433             states.add(state);
 434         }
 435         
 436         PseudoClass state = PseudoClass.getPseudoClass("three");
 437         states.add(state);
 438        
 439         assertEquals(expected, states.size());
 440     }
 441 
 442     @Test
 443     public void testPseudoClassState_isEmpty() {
 444         PseudoClassState states = new PseudoClassState();
 445         assertTrue(states.isEmpty());
 446     }
 447 
 448     @Test
 449     public void testPseudoClassState_isEmpty_negativeTest() {
 450         PseudoClassState states = new PseudoClassState();
 451         states.add(PseudoClass.getPseudoClass("pseudo-class"));
 452         assertTrue(states.isEmpty() == false);
 453     }
 454     
 455     @Test
 456     public void testPseudoClassState_isEmpty_whenBitMaskLengthGreaterThanOne() {
 457         PseudoClassState states = new PseudoClassState();
 458         PseudoClass state = null;
 459         try {
 460             for(int n=0; n<512; n++) {
 461                 state = PseudoClass.getPseudoClass("pseudoClass-"+Integer.valueOf(n));
 462             }
 463         } catch (IndexOutOfBoundsException exception) {
 464             fail();
 465         }
 466         
 467         states.add(state);
 468         assertTrue(states.isEmpty() == false);
 469     }
 470     
 471     @Test
 472     public void testPseudoClassState_equals() {
 473         
 474         String[] setA = new String[] {
 475             "zero", "one", "two", "three"
 476         };
 477         
 478         PseudoClassState aStates = new PseudoClassState();
 479         for(int n=0; n<setA.length; n++) {
 480             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 481         }
 482         
 483         String[] setB = new String[] {
 484             "zero", "one", "two", "three"            
 485         };
 486         PseudoClassState bStates = new PseudoClassState();
 487         for(int n=0; n<setB.length; n++) {
 488             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 489         }
 490                         
 491         assertTrue(aStates.equals(bStates));
 492     }    
 493     
 494     @Test
 495     public void testPseudoClassState_equals_negativeTest() {
 496         
 497         String[] setA = new String[] {
 498             "zero", "one", "two", "three"
 499         };
 500         
 501         PseudoClassState aStates = new PseudoClassState();
 502         for(int n=0; n<setA.length; n++) {
 503             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 504         }
 505         
 506         String[] setB = new String[] {
 507             "zero", "one", "two", "four"            
 508         };
 509         PseudoClassState bStates = new PseudoClassState();
 510         for(int n=0; n<setB.length; n++) {
 511             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 512         }
 513                         
 514         assertFalse(aStates.equals(bStates));
 515     }    
 516 
 517     @Test
 518     public void testPseudoClassState_retainAll() {
 519         
 520         String[] setA = new String[] {
 521             "zero", "one", "two", "three"
 522         };
 523         
 524         PseudoClassState aStates = new PseudoClassState();
 525         for(int n=0; n<setA.length; n++) {
 526             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 527         }
 528         
 529         String[] setB = new String[] {
 530             "four", "five", "one", "two", "three"
 531         };
 532         PseudoClassState bStates = new PseudoClassState();
 533         for(int n=0; n<setB.length; n++) {
 534             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 535         }
 536                 
 537         String[] expected = new String[] {
 538             "one", "two", "three"
 539         };
 540         
 541         aStates.retainAll(bStates);
 542         List<PseudoClass> states = new ArrayList<PseudoClass>();
 543         Iterator<PseudoClass> iter = aStates.iterator();
 544         while (iter.hasNext()) {
 545             states.add(iter.next());
 546         }
 547         
 548         assertEquals(expected.length, states.size(), 0.000001);
 549         
 550         for (int n=0; n<expected.length; n++) {
 551             PseudoClass state = PseudoClass.getPseudoClass(expected[n]);
 552             assertTrue(aStates.contains(state));
 553         }
 554     }
 555     
 556     @Test
 557     public void testPseudoClassState_retainAll_withEmptyStates() {
 558         
 559         PseudoClassState bStates = new PseudoClassState();
 560         PseudoClassState aStates = new PseudoClassState();        
 561         aStates.retainAll(bStates);
 562         List<PseudoClass> states = new ArrayList<PseudoClass>();
 563         Iterator<PseudoClass> iter = aStates.iterator();
 564         while (iter.hasNext()) {
 565             states.add(iter.next());
 566         }
 567         assertEquals(0, states.size(), 0.000001);
 568     }
 569     
 570     @Test
 571     public void testPseudoClassState_retainAll_withNullArg() {
 572         
 573         PseudoClassState aStates = new PseudoClassState();
 574         PseudoClassState bStates = null;
 575         aStates.retainAll(bStates);
 576         List<PseudoClass> states = new ArrayList<PseudoClass>();
 577         Iterator<PseudoClass> iter = aStates.iterator();
 578         while (iter.hasNext()) {
 579             states.add(iter.next());
 580         }
 581         assertEquals(0, states.size(), 0.000001);
 582         
 583     }
 584     
 585     @Test
 586     public void testPseudoClassState_retainAll_disjointYieldsEmpty() {
 587         
 588         String[] setA = new String[] {
 589             "zero", "one", "two", "three"
 590         };
 591         
 592         PseudoClassState aStates = new PseudoClassState();
 593         for(int n=0; n<setA.length; n++) {
 594             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 595         }
 596         
 597         String[] setB = new String[] {
 598             "four", "five"
 599         };
 600         PseudoClassState bStates = new PseudoClassState();
 601         for(int n=0; n<setB.length; n++) {
 602             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 603         }
 604                 
 605         String[] expected = new String[0];
 606         
 607         aStates.retainAll(bStates);
 608         List<PseudoClass> states = new ArrayList<PseudoClass>();
 609         Iterator<PseudoClass> iter = aStates.iterator();
 610         while (iter.hasNext()) {
 611             states.add(iter.next());
 612         }
 613         
 614         assertEquals(expected.length, states.size(), 0.000001);
 615         
 616         for (int n=0; n<expected.length; n++) {
 617             PseudoClass state = PseudoClass.getPseudoClass(expected[n]);
 618             assertTrue(aStates.contains(state));
 619         }
 620     }
 621     
 622     @Test
 623     public void testPseudoClassState_addAll() {
 624         
 625         String[] setA = new String[] {
 626             "zero", "one", "two", "three"
 627         };
 628         
 629         PseudoClassState aStates = new PseudoClassState();
 630         for(int n=0; n<setA.length; n++) {
 631             aStates.add(PseudoClass.getPseudoClass(setA[n]));
 632         }
 633         
 634         String[] setB = new String[] {
 635             "four", "five"
 636         };
 637         PseudoClassState bStates = new PseudoClassState();
 638         for(int n=0; n<setB.length; n++) {
 639             bStates.add(PseudoClass.getPseudoClass(setB[n]));
 640         }
 641                 
 642         String[] expected = new String[] {
 643             "zero", "one", "two", "three",
 644             "four", "five"            
 645         };
 646         
 647         aStates.addAll(bStates);
 648         List<PseudoClass> states = new ArrayList<PseudoClass>();
 649         Iterator<PseudoClass> iter = aStates.iterator();
 650         while (iter.hasNext()) {
 651             states.add(iter.next());
 652         }
 653         
 654         assertEquals(expected.length, states.size(), 0.000001);
 655         
 656         for (int n=0; n<expected.length; n++) {
 657             PseudoClass state = PseudoClass.getPseudoClass(expected[n]);
 658             assertTrue(aStates.contains(state));
 659         }
 660     }
 661     
 662     @Test
 663     public void testPseudoClassState_addAll_withEmptyStates() {
 664         
 665         PseudoClassState bStates = new PseudoClassState();
 666         PseudoClassState aStates = new PseudoClassState();        
 667         aStates.addAll(bStates);
 668         List<PseudoClass> states = new ArrayList<PseudoClass>();
 669         Iterator<PseudoClass> iter = aStates.iterator();
 670         while (iter.hasNext()) {
 671             states.add(iter.next());
 672         }
 673         assertEquals(0, states.size(), 0.000001);
 674     }
 675     
 676     @Test
 677     public void testPseudoClassState_addAll_withNullArgs() {
 678         
 679         PseudoClassState aStates = new PseudoClassState();
 680         PseudoClassState bStates = null;
 681         aStates.addAll(bStates);
 682         List<PseudoClass> states = new ArrayList<PseudoClass>();
 683         Iterator<PseudoClass> iter = aStates.iterator();
 684         while (iter.hasNext()) {
 685             states.add(iter.next());
 686         }
 687         assertEquals(0, states.size(), 0.000001);
 688         
 689     }
 690     
 691     @Test
 692     public void testPseudoClassState_getPseudoClasses() {
 693         
 694         String[] pseudoClasses = new String[] {
 695             "zero", "one", "two", "three"
 696         };
 697         List<PseudoClass> expected = new ArrayList<PseudoClass>();
 698         PseudoClassState states = new PseudoClassState();
 699         for(int n=0; n<pseudoClasses.length; n++) {
 700             PseudoClass state = PseudoClass.getPseudoClass(pseudoClasses[n]);
 701             states.add(state);
 702             expected.add(state);            
 703         }
 704         
 705         List<PseudoClass> stateList = new ArrayList<PseudoClass>();
 706         Iterator<PseudoClass> iter = states.iterator();
 707         while (iter.hasNext()) {
 708             stateList.add(iter.next());
 709         }
 710         
 711         assertTrue(expected.containsAll(stateList));
 712     }
 713         
 714     @Test
 715     public void testPseudoClassState_toString() {
 716         
 717         String[] pseudoClasses = new String[] {
 718             "zero", "one", "two", "three"
 719         };
 720         
 721         PseudoClassState states = new PseudoClassState();
 722         for(int n=0; n<pseudoClasses.length; n++) {
 723             states.add(PseudoClass.getPseudoClass(pseudoClasses[n]));
 724         }
 725         
 726         List<PseudoClass> stateList = new ArrayList<PseudoClass>();
 727         Iterator<PseudoClass> iter = states.iterator();
 728         while (iter.hasNext()) {
 729             stateList.add(iter.next());
 730         }
 731         String expected = stateList.toString();
 732         
 733         String result = states.toString();
 734         
 735         assertEquals(expected, result);
 736     }
 737 
 738     @Test public void testPseudoClassState_iterator() {
 739         
 740         PseudoClass[] pseudoClasses = new PseudoClass[4];
 741         PseudoClassState states = new PseudoClassState();
 742         
 743         for (int n=0; n<pseudoClasses.length; n++) {
 744             pseudoClasses[n] = PseudoClass.getPseudoClass(Integer.toString(n));
 745             states.add(pseudoClasses[n]);
 746         };
 747         
 748         int iterations = 0;
 749         Iterator<PseudoClass> iter = states.iterator();
 750         while(iter.hasNext()) {
 751             
 752             iterations += 1;
 753             assertTrue (iterations+">"+pseudoClasses.length, iterations <= pseudoClasses.length);
 754             
 755             PseudoClass pseudoClass = iter.next();
 756             assertEquals (pseudoClass, pseudoClasses[iterations-1]);
 757         }
 758         
 759         assertTrue (pseudoClasses.length+"!="+iterations, pseudoClasses.length == iterations);
 760         
 761     }
 762 
 763     @Test public void testPseudoClassState_iterator_withLargeNumberOfPsuedoClasses() {
 764         
 765         PseudoClass[] pseudoClasses = new PseudoClass[Long.SIZE*3];
 766         PseudoClassState states = new PseudoClassState();
 767         
 768         for (int n=0; n<pseudoClasses.length; n++) {
 769             pseudoClasses[n] = PseudoClass.getPseudoClass(Integer.toString(n));
 770             states.add(pseudoClasses[n]);
 771         };
 772         
 773         int iterations = 0;
 774         Iterator<PseudoClass> iter = states.iterator();
 775         while(iter.hasNext()) {
 776             
 777             iterations += 1;
 778             assertTrue (iterations+">"+pseudoClasses.length, iterations <= pseudoClasses.length);
 779             
 780             PseudoClass pseudoClass = iter.next();
 781             assertEquals (pseudoClass, pseudoClasses[iterations-1]);
 782         }
 783         
 784         assertTrue (pseudoClasses.length+"!="+iterations, pseudoClasses.length == iterations);
 785         
 786     }
 787 
 788     @Test public void testPseudoClassState_iterator_remove() {
 789         
 790         PseudoClass[] pseudoClasses = new PseudoClass[4];
 791         PseudoClassState states = new PseudoClassState();
 792         
 793         for (int n=0; n<pseudoClasses.length; n++) {
 794             pseudoClasses[n] = PseudoClass.getPseudoClass(Integer.toString(n));
 795             states.add(pseudoClasses[n]);
 796         };
 797         
 798         int iterations = 0;
 799         int nPseudoClasses = pseudoClasses.length;
 800         Iterator<PseudoClass> iter = states.iterator();
 801         while(iter.hasNext()) {
 802                      
 803             ++iterations; 
 804             
 805             if ((iterations % 2) == 0) {
 806                 iter.remove();
 807                 --nPseudoClasses;
 808                 assertFalse(states.contains(pseudoClasses[iterations-1]));
 809             }
 810         }
 811         
 812         assertTrue (nPseudoClasses+"!="+states.size(), nPseudoClasses == states.size());
 813         
 814     }
 815 
 816     @Test public void testPseudoClassState_iterator_remove_withLargeNumberOfPseudoClasses() {
 817         
 818         PseudoClass[] pseudoClasses = new PseudoClass[Long.SIZE*3];
 819         PseudoClassState states = new PseudoClassState();
 820         
 821         for (int n=0; n<pseudoClasses.length; n++) {
 822             pseudoClasses[n] = PseudoClass.getPseudoClass(Integer.toString(n));
 823             states.add(pseudoClasses[n]);
 824         };
 825         
 826         int iterations = 0;
 827         int nPseudoClasses = pseudoClasses.length;
 828         Iterator<PseudoClass> iter = states.iterator();
 829         while(iter.hasNext()) {
 830                         
 831             ++iterations;
 832             
 833             if ((iterations % 2) == 0) {
 834                 iter.remove();
 835                 --nPseudoClasses;
 836                 assertFalse(states.contains(pseudoClasses[iterations-1]));
 837             }
 838         }
 839         
 840         assertTrue (nPseudoClasses+"!="+states.size(), nPseudoClasses == states.size());
 841         
 842     }
 843 
 844     int nObservations = 0;
 845 
 846     @Test public void testObservablePseudoClass_listener_add() {
 847 
 848 
 849         final PseudoClass[] expectedObservations = new PseudoClass[] {
 850                 PseudoClass.getPseudoClass("ONE"),
 851                 PseudoClass.getPseudoClass("TWO"),
 852                 PseudoClass.getPseudoClass("THREE")
 853 
 854         };
 855         final int nObservationsExpected = expectedObservations.length;
 856         nObservations = 0;
 857 
 858         ObservableSet<PseudoClass> pseudoClasses = new PseudoClassState();
 859         pseudoClasses.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
 860             if (change.wasAdded()) {
 861                 assert (nObservations < nObservationsExpected);
 862                 PseudoClass observed = change.getElementAdded();
 863                 assertSame(expectedObservations[nObservations], observed);
 864                 nObservations += 1;
 865             } else {
 866                 fail();
 867             }
 868         });
 869 
 870         for (int n=0; n<expectedObservations.length; n++) {
 871             pseudoClasses.add(expectedObservations[n]);
 872         };
 873 
 874         assertEquals(nObservationsExpected, nObservations);
 875 
 876     }
 877 
 878     @Test public void testObservablePseudoClass_listener_remove() {
 879 
 880 
 881         final PseudoClass[] expectedObservations = new PseudoClass[] {
 882                 PseudoClass.getPseudoClass("ONE"),
 883                 PseudoClass.getPseudoClass("TWO"),
 884                 PseudoClass.getPseudoClass("THREE")
 885 
 886         };
 887         final int nObservationsExpected = expectedObservations.length;
 888         nObservations = 0;
 889 
 890         ObservableSet<PseudoClass> pseudoClasses = new PseudoClassState();
 891         for (int n=0; n<expectedObservations.length; n++) {
 892             pseudoClasses.add(expectedObservations[n]);
 893         };
 894 
 895         pseudoClasses.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
 896             if (change.wasRemoved()) {
 897                 assert (nObservations < nObservationsExpected);
 898                 PseudoClass observed = change.getElementRemoved();
 899                 assertSame(expectedObservations[nObservations], observed);
 900                 nObservations += 1;
 901             } else {
 902                 fail();
 903             }
 904         });
 905 
 906         for (int n=0; n<expectedObservations.length; n++) {
 907             pseudoClasses.remove(expectedObservations[n]);
 908         };
 909 
 910         assertEquals(nObservationsExpected, nObservations);
 911 
 912     }
 913 
 914     @Test public void testObservablePseudoClass_listener_iter_remove() {
 915 
 916 
 917         final PseudoClass[] expectedObservations = new PseudoClass[] {
 918                 PseudoClass.getPseudoClass("ONE"),
 919                 PseudoClass.getPseudoClass("TWO"),
 920                 PseudoClass.getPseudoClass("THREE")
 921 
 922         };
 923         final int nObservationsExpected = expectedObservations.length;
 924         nObservations = 0;
 925 
 926         ObservableSet<PseudoClass> pseudoClasses = new PseudoClassState();
 927         for (int n=0; n<expectedObservations.length; n++) {
 928             pseudoClasses.add(expectedObservations[n]);
 929         };
 930 
 931         pseudoClasses.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
 932             if (change.wasRemoved()) {
 933                 assert (nObservations < nObservationsExpected);
 934                 PseudoClass observed = change.getElementRemoved();
 935                 assertSame(expectedObservations[nObservations], observed);
 936                 nObservations += 1;
 937             } else {
 938                 fail();
 939             }
 940         });
 941 
 942         for (Iterator<PseudoClass> iter = pseudoClasses.iterator(); iter.hasNext();) {
 943             iter.remove();
 944         };
 945 
 946         assertEquals(nObservationsExpected, nObservations);
 947 
 948     }
 949 
 950     @Test public void testObservablePseudoClass_listener_addAll() {
 951 
 952 
 953         final PseudoClass[] expectedObservations = new PseudoClass[] {
 954                 PseudoClass.getPseudoClass("ONE"),
 955                 PseudoClass.getPseudoClass("TWO"),
 956                 PseudoClass.getPseudoClass("THREE")
 957 
 958         };
 959         final int nObservationsExpected = expectedObservations.length;
 960         nObservations = 0;
 961 
 962         Set<PseudoClass> pseudoClassesToAdd = new PseudoClassState();
 963         for (int n=0; n<expectedObservations.length; n++) {
 964             pseudoClassesToAdd.add(expectedObservations[n]);
 965         };
 966 
 967         ObservableSet<PseudoClass> pseudoClasses = new PseudoClassState();
 968         pseudoClasses.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
 969             if (change.wasAdded()) {
 970                 assert (nObservations < nObservationsExpected);
 971                 PseudoClass observed = change.getElementAdded();
 972                 assertSame(expectedObservations[nObservations], observed);
 973                 nObservations += 1;
 974             } else {
 975                 fail();
 976             }
 977         });
 978 
 979         pseudoClasses.addAll(pseudoClassesToAdd);
 980 
 981         assertEquals(nObservationsExpected, nObservations);
 982 
 983     }
 984 
 985     @Test public void testObservablePseudoClass_listener_removeAll() {
 986 
 987 
 988         final PseudoClass[] pseudoClassesToRemove = new PseudoClass[] {
 989                 PseudoClass.getPseudoClass("TWO"),
 990                 PseudoClass.getPseudoClass("THREE")
 991 
 992         };
 993 
 994         final PseudoClass[] pseudoClasses = new PseudoClass[] {
 995                 PseudoClass.getPseudoClass("ONE"),
 996                 PseudoClass.getPseudoClass("TWO"),
 997                 PseudoClass.getPseudoClass("THREE"),
 998                 PseudoClass.getPseudoClass("FOUR")
 999 
1000         };
1001 
1002         final int nObservationsExpected = pseudoClassesToRemove.length;
1003         nObservations = 0;
1004 
1005         Set<PseudoClass> other = new PseudoClassState();
1006         for (int n=0; n<pseudoClassesToRemove.length; n++) {
1007             other.add(pseudoClassesToRemove[n]);
1008         };
1009 
1010         ObservableSet<PseudoClass> master = new PseudoClassState();
1011         for (int n=0; n<pseudoClasses.length; n++) {
1012             master.add(pseudoClasses[n]);
1013         };
1014 
1015         master.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
1016             if (change.wasRemoved()) {
1017                 assert (nObservations < nObservationsExpected);
1018                 PseudoClass observed = change.getElementRemoved();
1019                 assertSame(pseudoClassesToRemove[nObservations], observed);
1020                 nObservations += 1;
1021             } else {
1022                 fail();
1023             }
1024         });
1025 
1026         master.removeAll(other);
1027 
1028         assertEquals(nObservationsExpected, nObservations);
1029         assertEquals(pseudoClasses.length-pseudoClassesToRemove.length, master.size());
1030 
1031     }
1032 
1033     @Test public void testObservablePseudoClass_listener_retainAll() {
1034 
1035 
1036         final PseudoClass[] pseudoClassesToRetain = new PseudoClass[] {
1037                 PseudoClass.getPseudoClass("TWO"),
1038                 PseudoClass.getPseudoClass("THREE")
1039 
1040         };
1041 
1042         final PseudoClass[] removedPseudoClasses = new PseudoClass[] {
1043                 PseudoClass.getPseudoClass("ONE"),
1044                 PseudoClass.getPseudoClass("FOUR")
1045 
1046         };
1047 
1048         final PseudoClass[] pseudoClasses = new PseudoClass[] {
1049                 PseudoClass.getPseudoClass("ONE"),
1050                 PseudoClass.getPseudoClass("TWO"),
1051                 PseudoClass.getPseudoClass("THREE"),
1052                 PseudoClass.getPseudoClass("FOUR")
1053 
1054         };
1055 
1056         final int nObservationsExpected = pseudoClassesToRetain.length;
1057         nObservations = 0;
1058 
1059         Set<PseudoClass> other = new PseudoClassState();
1060         for (int n=0; n<pseudoClassesToRetain.length; n++) {
1061             other.add(pseudoClassesToRetain[n]);
1062         };
1063 
1064         ObservableSet<PseudoClass> master = new PseudoClassState();
1065         for (int n=0; n<pseudoClasses.length; n++) {
1066             master.add(pseudoClasses[n]);
1067         };
1068 
1069         master.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
1070             if (change.wasRemoved()) {
1071                 assert (nObservations < nObservationsExpected);
1072                 PseudoClass observed = change.getElementRemoved();
1073                 assertSame(removedPseudoClasses[nObservations], observed);
1074                 nObservations += 1;
1075             } else {
1076                 fail();
1077             }
1078         });
1079 
1080         master.retainAll(other);
1081 
1082         assertEquals(nObservationsExpected, nObservations);
1083         assertEquals(pseudoClassesToRetain.length, master.size());
1084 
1085     }
1086 
1087     @Test public void testObservablePseudoClass_listener_clear() {
1088 
1089 
1090         final PseudoClass[] pseudoClasses = new PseudoClass[] {
1091                 PseudoClass.getPseudoClass("ONE"),
1092                 PseudoClass.getPseudoClass("TWO"),
1093                 PseudoClass.getPseudoClass("THREE"),
1094                 PseudoClass.getPseudoClass("FOUR")
1095 
1096         };
1097 
1098         final int nObservationsExpected = pseudoClasses.length;
1099         nObservations = 0;
1100 
1101         ObservableSet<PseudoClass> master = new PseudoClassState();
1102         for (int n=0; n<pseudoClasses.length; n++) {
1103             master.add(pseudoClasses[n]);
1104         };
1105 
1106         master.addListener((SetChangeListener.Change<? extends PseudoClass> change) -> {
1107             if (change.wasRemoved()) {
1108                 assert (nObservations < nObservationsExpected);
1109                 PseudoClass observed = change.getElementRemoved();
1110                 assertSame(pseudoClasses[nObservations], observed);
1111                 nObservations += 1;
1112             } else {
1113                 fail();
1114             }
1115         });
1116 
1117         master.clear();
1118 
1119         assertEquals(nObservationsExpected, nObservations);
1120         assertTrue(master.isEmpty());
1121 
1122     }
1123 
1124     @Test public void testObservablePseudoClass_listener_getSet_unmodifiable() {
1125 
1126         final ObservableSet<PseudoClass> master = new PseudoClassState();
1127 
1128         master.addListener(new SetChangeListener<PseudoClass>() {
1129 
1130             @Override
1131             public void onChanged(SetChangeListener.Change<? extends PseudoClass> change) {
1132                 master.removeListener(this);
1133                 try {
1134                     ObservableSet set = change.getSet();
1135                     set.add(PseudoClass.getPseudoClass("TWO"));
1136                     fail();
1137                 } catch (UnsupportedOperationException e) {
1138                     // This is the exception we expect from an unmodifiable set
1139                 } catch (Exception other) {
1140                     fail(other.getMessage());
1141                 }
1142             }
1143         });
1144 
1145         master.add(PseudoClass.getPseudoClass("ONE"));
1146 
1147     }
1148 
1149     @Test public void testRetainAllOfEmptySetResultsInEmptySet() {
1150 
1151         final PseudoClass[] pseudoClasses = new PseudoClass[] {
1152                 PseudoClass.getPseudoClass("ONE"),
1153                 PseudoClass.getPseudoClass("TWO"),
1154                 PseudoClass.getPseudoClass("THREE"),
1155                 PseudoClass.getPseudoClass("FOUR")
1156 
1157         };
1158 
1159         Set<PseudoClass> setA = new PseudoClassState();
1160         for (int n=0; n<pseudoClasses.length; n++) {
1161             setA.add(pseudoClasses[n]);
1162         };
1163 
1164         Set<PseudoClass> setB = new PseudoClassState();
1165 
1166         assertTrue(setA.retainAll(setB));
1167 
1168         assertArrayEquals(new long[0], ((PseudoClassState)setA).getBits());
1169 
1170     }
1171 
1172     @Test public void testRemoveAllOfSameSetResultsInEmptySet() {
1173 
1174         final PseudoClass[] pseudoClasses = new PseudoClass[] {
1175                 PseudoClass.getPseudoClass("ONE"),
1176                 PseudoClass.getPseudoClass("TWO"),
1177                 PseudoClass.getPseudoClass("THREE"),
1178                 PseudoClass.getPseudoClass("FOUR")
1179 
1180         };
1181 
1182         Set<PseudoClass> setA = new PseudoClassState();
1183         for (int n=0; n<pseudoClasses.length; n++) {
1184             setA.add(pseudoClasses[n]);
1185         };
1186 
1187         assertTrue(setA.removeAll(setA));
1188 
1189         assertArrayEquals(new long[0], ((PseudoClassState)setA).getBits());
1190 
1191     }
1192 
1193     @Test public void testRemoveLastBitResultsInEmptySet() {
1194 
1195         final PseudoClass[] pseudoClasses = new PseudoClass[] {
1196                 PseudoClass.getPseudoClass("ONE"),
1197                 PseudoClass.getPseudoClass("TWO"),
1198                 PseudoClass.getPseudoClass("THREE"),
1199                 PseudoClass.getPseudoClass("FOUR")
1200 
1201         };
1202 
1203         Set<PseudoClass> setA = new PseudoClassState();
1204         for (int n=0; n<pseudoClasses.length; n++) {
1205             setA.add(pseudoClasses[n]);
1206         };
1207 
1208         for (int n=0; n<pseudoClasses.length; n++) {
1209             assertTrue(setA.remove(pseudoClasses[n]));
1210         };
1211 
1212         assertArrayEquals(new long[0], ((PseudoClassState)setA).getBits());
1213 
1214     }
1215 
1216     @Test public void testRemoveLastBitByIteratorResultsInEmptySet() {
1217 
1218         final PseudoClass[] pseudoClasses = new PseudoClass[] {
1219                 PseudoClass.getPseudoClass("ONE"),
1220                 PseudoClass.getPseudoClass("TWO"),
1221                 PseudoClass.getPseudoClass("THREE"),
1222                 PseudoClass.getPseudoClass("FOUR")
1223 
1224         };
1225 
1226         Set<PseudoClass> setA = new PseudoClassState();
1227         for (int n=0; n<pseudoClasses.length; n++) {
1228             setA.add(pseudoClasses[n]);
1229         };
1230 
1231         Iterator<PseudoClass> iterator = setA.iterator();
1232         while (iterator.hasNext()) {
1233             iterator.remove();
1234         }
1235 
1236         assertArrayEquals(new long[0], ((PseudoClassState)setA).getBits());
1237 
1238     }
1239 
1240     @Test public void testAddEmptyToEmptyResultsInEmptySet() {
1241 
1242         Set<PseudoClass> setA = new PseudoClassState();
1243         Set<PseudoClass> setB = new PseudoClassState();
1244         assertFalse(setA.addAll(setB));
1245         assertArrayEquals(new long[0], ((PseudoClassState)setA).getBits());
1246 
1247     }
1248 
1249 }