1 /* 2 * Copyright (c) 2015, 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 javafx.beans.property; 27 28 import com.sun.javafx.binding.ExpressionHelperUtility; 29 import java.util.Arrays; 30 import java.util.List; 31 import static org.junit.Assert.assertEquals; 32 import org.junit.Before; 33 import org.junit.Ignore; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.junit.runners.Parameterized; 37 38 @RunWith(Parameterized.class) 39 public class PropertyBaseTest<T> { 40 41 @FunctionalInterface 42 public interface PropertyFactory<T> { 43 public Property<T> createProperty(); 44 } 45 46 public static class Factory<T> { 47 48 private PropertyFactory<T> propertyFactory; 49 private PropertyFactory<T> observableFactory; 50 private T value; 51 52 public Factory(PropertyFactory<T> propertyFactory, 53 PropertyFactory<T> observableFactory, T value) 54 { 55 this.propertyFactory = propertyFactory; 56 this.observableFactory = observableFactory; 57 this.value = value; 58 } 59 60 public Property<T> createProperty() { 61 return propertyFactory.createProperty(); 62 } 63 64 public Property<T> createObservable() { 65 return observableFactory.createProperty(); 66 } 67 68 public T getValue() { 69 return value; 70 } 71 } 72 73 @Parameterized.Parameters 74 public static List<Object[]> data() { 75 return Arrays.asList(new Object[][] { 76 // primitive binding 77 // Property->Listener->Value 78 { new Factory(() -> new SimpleBooleanProperty(), () -> new SimpleBooleanProperty(), true) }, 79 { new Factory(() -> new SimpleDoubleProperty(), () -> new SimpleDoubleProperty(), 1.0) }, 80 { new Factory(() -> new SimpleFloatProperty(), () -> new SimpleFloatProperty(), 1.0f) }, 81 { new Factory(() -> new SimpleIntegerProperty(), () -> new SimpleIntegerProperty(), 1) }, 82 { new Factory(() -> new SimpleLongProperty(), () -> new SimpleLongProperty(), 1L) }, 83 // generic with wrapper 84 // Property->Listener->Binding->BindingHelperObserver->Value 85 { new Factory(() -> new SimpleBooleanProperty(), () -> new SimpleObjectProperty<>(), true) }, 86 { new Factory(() -> new SimpleDoubleProperty(), () -> new SimpleObjectProperty<>(), 1.0) }, 87 { new Factory(() -> new SimpleFloatProperty(), () -> new SimpleObjectProperty<>(), 1.0f) }, 88 { new Factory(() -> new SimpleIntegerProperty(), () -> new SimpleObjectProperty<>(), 1) }, 89 { new Factory(() -> new SimpleLongProperty(), () -> new SimpleObjectProperty<>(), 1L) }, 90 // generic 91 // Property->Listener->Value 92 { new Factory(() -> new SimpleObjectProperty(), () -> new SimpleObjectProperty<>(), new Object()) }, 93 { new Factory(() -> new SimpleStringProperty(), () -> new SimpleObjectProperty<>(), "1") }, 94 // the same as generic 95 { new Factory(() -> new SimpleStringProperty(), () -> new SimpleStringProperty(), "1") }, 96 }); 97 } 98 99 public PropertyBaseTest(Factory<T> factory) { 100 this.factory = factory; 101 } 102 103 @Before 104 public void setUp() { 105 property = factory.createProperty(); 106 observable = factory.createObservable(); 107 value = factory.getValue(); 108 } 109 110 private Factory<T> factory; 111 private Property<T> property; 112 private Property<T> observable; 113 private T value; 114 115 @Test 116 public void testUnbindAfterInvalidation() { 117 property.bind(observable); 118 assertEquals(1, ExpressionHelperUtility.getInvalidationListeners(observable).size()); 119 120 property = null; 121 System.gc(); 122 123 observable.setValue(value); 124 assertEquals(0, ExpressionHelperUtility.getInvalidationListeners(observable).size()); 125 } 126 127 @Test 128 public void testTrimAfterGC() { 129 Property<T> p1 = factory.createProperty(); 130 Property<T> p2 = factory.createProperty(); 131 p1.bind(observable); // creates SingleInvalidation 132 p2.bind(observable); // creates Generic with 2 listeners 133 assertEquals(2, ExpressionHelperUtility.getInvalidationListeners(observable).size()); 134 135 p1 = null; 136 p2 = null; 137 System.gc(); 138 139 property.bind(observable); // calls trim 140 assertEquals(1, ExpressionHelperUtility.getInvalidationListeners(observable).size()); 141 } 142 143 @Ignore("8130458") 144 @Test 145 public void testUnbindGenericWrapper() { 146 property.bind(observable); 147 assertEquals(1, ExpressionHelperUtility.getInvalidationListeners(observable).size()); 148 149 property.unbind(); // should unbind wrapper from observable 150 assertEquals(0, ExpressionHelperUtility.getInvalidationListeners(observable).size()); 151 } 152 }