1 /*
   2  * Copyright (c) 2011, 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.binding;
  27 
  28 import javafx.beans.binding.Bindings;
  29 import javafx.collections.FXCollections;
  30 import javafx.collections.ObservableList;
  31 import org.junit.Before;
  32 import org.junit.Test;
  33 
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.List;
  37 
  38 import static org.junit.Assert.*;
  39 
  40 public class ContentBindingListTest {
  41 
  42     private List<Integer> op1;
  43     private ObservableList<Integer> op2;
  44     private ObservableList<Integer> op3;
  45     private List<Integer> list0;
  46     private List<Integer> list1;
  47     private List<Integer> list2;
  48 
  49     @Before
  50     public void setUp() {
  51         list0 = new ArrayList<Integer>();
  52         list1 = new ArrayList<Integer>(Arrays.asList(0));
  53         list2 = new ArrayList<Integer>(Arrays.asList(2, 1));
  54 
  55         op1 = new ArrayList<Integer>(list1);
  56         op2 = FXCollections.observableArrayList(list2);
  57         op3 = FXCollections.observableArrayList(list0);
  58     }
  59 
  60     @Test
  61     public void testBind() {
  62         List<Integer> list2_sorted = new ArrayList<Integer>(Arrays.asList(1, 2));
  63 
  64         Bindings.bindContent(op1, op2);
  65         System.gc(); // making sure we did not not overdo weak references
  66         assertEquals(list2, op1);
  67         assertEquals(list2, op2);
  68 
  69         op2.setAll(list1);
  70         assertEquals(list1, op1);
  71         assertEquals(list1, op2);
  72 
  73         op2.setAll(list0);
  74         assertEquals(list0, op1);
  75         assertEquals(list0, op2);
  76 
  77         op2.setAll(list2);
  78         assertEquals(list2, op1);
  79         assertEquals(list2, op2);
  80 
  81         FXCollections.sort(op2);
  82         assertEquals(list2_sorted, op1);
  83         assertEquals(list2_sorted, op2);
  84     }
  85 
  86     @Test(expected = NullPointerException.class)
  87     public void testBind_Null_X() {
  88         Bindings.bindContent(null, op2);
  89     }
  90 
  91     @Test(expected = NullPointerException.class)
  92     public void testBind_X_Null() {
  93         Bindings.bindContent(op1, null);
  94     }
  95 
  96     @Test(expected = IllegalArgumentException.class)
  97     public void testBind_X_Self() {
  98         Bindings.bindContent(op2, op2);
  99     }
 100 
 101     @Test
 102     public void testUnbind() {
 103         // unbind non-existing binding => no-op
 104         Bindings.unbindContent(op1, op2);
 105 
 106         Bindings.bindContent(op1, op2);
 107         System.gc(); // making sure we did not not overdo weak references
 108         assertEquals(list2, op1);
 109         assertEquals(list2, op2);
 110 
 111         Bindings.unbindContent(op1, op2);
 112         System.gc();
 113         assertEquals(list2, op1);
 114         assertEquals(list2, op2);
 115 
 116         op1.clear();
 117         assertEquals(list0, op1);
 118         assertEquals(list2, op2);
 119 
 120         op2.setAll(list1);
 121         assertEquals(list0, op1);
 122         assertEquals(list1, op2);
 123     }
 124 
 125     @Test(expected = NullPointerException.class)
 126     public void testUnbind_Null_X() {
 127         Bindings.unbindContent(null, op2);
 128     }
 129 
 130     @Test(expected = NullPointerException.class)
 131     public void testUnbind_X_Null() {
 132         Bindings.unbindContent(op1, null);
 133     }
 134 
 135     @Test(expected = IllegalArgumentException.class)
 136     public void testUnbind_X_Self() {
 137         Bindings.unbindContent(op2, op2);
 138     }
 139 
 140     @Test
 141     public void testChaining() {
 142         Bindings.bindContent(op1, op2);
 143         Bindings.bindContent(op2, op3);
 144         System.gc(); // making sure we did not not overdo weak references
 145         assertEquals(list0, op1);
 146         assertEquals(list0, op2);
 147         assertEquals(list0, op3);
 148 
 149         op3.setAll(list1);
 150         assertEquals(list1, op1);
 151         assertEquals(list1, op2);
 152         assertEquals(list1, op3);
 153 
 154         // now unbind 
 155         Bindings.unbindContent(op1, op2);
 156         System.gc(); // making sure we did not not overdo weak references
 157         assertEquals(list1, op1);
 158         assertEquals(list1, op2);
 159         assertEquals(list1, op3);
 160 
 161         op3.setAll(list2);
 162         assertEquals(list1, op1);
 163         assertEquals(list2, op2);
 164         assertEquals(list2, op3);
 165     }
 166 
 167     @Test
 168     public void testHashCode() {
 169         final int hc1 = ContentBinding.bind(op1, op2).hashCode();
 170         ContentBinding.unbind(op1, op2);
 171         final int hc2 = ContentBinding.bind(op1, op2).hashCode();
 172         assertEquals(hc1, hc2);
 173     }
 174 
 175     @Test
 176     public void testEquals() {
 177         final Object golden = ContentBinding.bind(op1, op2);
 178         ContentBinding.unbind(op1, op2);
 179 
 180         assertTrue(golden.equals(golden));
 181         assertFalse(golden.equals(null));
 182         assertFalse(golden.equals(op1));
 183         assertTrue(golden.equals(ContentBinding.bind(op1, op2)));
 184         ContentBinding.unbind(op1, op2);
 185         assertFalse(golden.equals(ContentBinding.bind(op3, op2)));
 186         ContentBinding.unbind(op2, op3);
 187         assertFalse(golden.equals(ContentBinding.bind(op2, op3)));
 188         ContentBinding.unbind(op2, op3);
 189     }
 190 
 191     @Test
 192     public void testEqualsWithGCedProperty() {
 193         final Object binding1 = ContentBinding.bind(op1, op2);
 194         ContentBinding.unbind(op1, op2);
 195         final Object binding2 = ContentBinding.bind(op1, op2);
 196         ContentBinding.unbind(op1, op2);
 197         op1 = null;
 198         System.gc();
 199 
 200         assertTrue(binding1.equals(binding1));
 201         assertFalse(binding1.equals(binding2));
 202     }
 203 
 204     @Test
 205     public void testAlreadyBound() {
 206         // get the current exception handler before replacing with our own,
 207         // as ListListenerHelper intercepts the exception otherwise
 208         final Thread.UncaughtExceptionHandler exceptionHandler =
 209                 Thread.currentThread().getUncaughtExceptionHandler();
 210         Thread.currentThread().setUncaughtExceptionHandler((t, e) -> {
 211                 throw new AssertionError("We don't expect any exceptions in this test!", e);
 212             }
 213         );
 214 
 215         ContentBinding.bind(op1, op2);
 216         ContentBinding.bind(op1, op2);
 217         op2.remove(1);
 218 
 219         // reset the exception handler
 220         Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
 221     }
 222 }