changeset 9268:98e22e3d6bdd

8136465: MapProperty.removeListener(changlistener) removes all the listeners not just one Reviewed-by: ckyang
author vadim
date Wed, 23 Sep 2015 12:55:26 +0300
parents 98bb3d975bb6
children ac7f30bdca65
files modules/base/src/main/java/com/sun/javafx/binding/MapExpressionHelper.java modules/base/src/main/java/com/sun/javafx/binding/SetExpressionHelper.java modules/base/src/test/java/test/com/sun/javafx/binding/ListExpressionHelperTest.java modules/base/src/test/java/test/com/sun/javafx/binding/MapExpressionHelperTest.java modules/base/src/test/java/test/com/sun/javafx/binding/SetExpressionHelperTest.java
diffstat 5 files changed, 542 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/modules/base/src/main/java/com/sun/javafx/binding/MapExpressionHelper.java	Tue Sep 22 13:55:16 2015 -0400
+++ b/modules/base/src/main/java/com/sun/javafx/binding/MapExpressionHelper.java	Wed Sep 23 12:55:26 2015 +0300
@@ -403,6 +403,8 @@
                             }
                             invalidationListeners = null;
                             invalidationSize = 0;
+                        } else if ((invalidationSize == 2) && (changeSize == 0) && (mapChangeSize == 0)) {
+                            return new SingleInvalidation<>(observable, invalidationListeners[1-index]);
                         } else {
                             final int numMoved = invalidationSize - index - 1;
                             final InvalidationListener[] oldListeners = invalidationListeners;
@@ -415,7 +417,7 @@
                             }
                             invalidationSize--;
                             if (!locked) {
-                                invalidationListeners[--invalidationSize] = null; // Let gc do its work
+                                invalidationListeners[invalidationSize] = null; // Let gc do its work
                             }
                         }
                         break;
@@ -463,6 +465,8 @@
                             }
                             changeListeners = null;
                             changeSize = 0;
+                        } else if ((changeSize == 2) && (invalidationSize == 0) && (mapChangeSize == 0)) {
+                            return new SingleChange<>(observable, changeListeners[1-index]);
                         } else {
                             final int numMoved = changeSize - index - 1;
                             final ChangeListener<? super ObservableMap<K, V>>[] oldListeners = changeListeners;
@@ -475,7 +479,7 @@
                             }
                             changeSize--;
                             if (!locked) {
-                                changeListeners[--changeSize] = null; // Let gc do its work
+                                changeListeners[changeSize] = null; // Let gc do its work
                             }
                         }
                         break;
@@ -523,6 +527,8 @@
                             }
                             mapChangeListeners = null;
                             mapChangeSize = 0;
+                        } else if ((mapChangeSize == 2) && (invalidationSize == 0) && (changeSize == 0)) {
+                            return new SingleMapChange<>(observable, mapChangeListeners[1-index]);
                         } else {
                             final int numMoved = mapChangeSize - index - 1;
                             final MapChangeListener<? super K, ? super V>[] oldListeners = mapChangeListeners;
@@ -535,7 +541,7 @@
                             }
                             mapChangeSize--;
                             if (!locked) {
-                                mapChangeListeners[--mapChangeSize] = null; // Let gc do its work
+                                mapChangeListeners[mapChangeSize] = null; // Let gc do its work
                             }
                         }
                         break;
--- a/modules/base/src/main/java/com/sun/javafx/binding/SetExpressionHelper.java	Tue Sep 22 13:55:16 2015 -0400
+++ b/modules/base/src/main/java/com/sun/javafx/binding/SetExpressionHelper.java	Wed Sep 23 12:55:26 2015 +0300
@@ -394,6 +394,8 @@
                             }
                             invalidationListeners = null;
                             invalidationSize = 0;
+                        } else if ((invalidationSize == 2) && (changeSize == 0) && (setChangeSize == 0)) {
+                            return new SingleInvalidation<>(observable, invalidationListeners[1-index]);
                         } else {
                             final int numMoved = invalidationSize - index - 1;
                             final InvalidationListener[] oldListeners = invalidationListeners;
@@ -406,7 +408,7 @@
                             }
                             invalidationSize--;
                             if (!locked) {
-                                invalidationListeners[--invalidationSize] = null; // Let gc do its work
+                                invalidationListeners[invalidationSize] = null; // Let gc do its work
                             }
                         }
                         break;
@@ -454,6 +456,8 @@
                             }
                             changeListeners = null;
                             changeSize = 0;
+                        } else if ((changeSize == 2) && (invalidationSize == 0) && (setChangeSize == 0)) {
+                            return new SingleChange<>(observable, changeListeners[1-index]);
                         } else {
                             final int numMoved = changeSize - index - 1;
                             final ChangeListener<? super ObservableSet<E>>[] oldListeners = changeListeners;
@@ -514,6 +518,8 @@
                             }
                             setChangeListeners = null;
                             setChangeSize = 0;
+                        } else if ((setChangeSize == 2) && (invalidationSize == 0) && (changeSize == 0)) {
+                            return new SingleSetChange<>(observable, setChangeListeners[1-index]);
                         } else {
                             final int numMoved = setChangeSize - index - 1;
                             final SetChangeListener<? super E>[] oldListeners = setChangeListeners;
--- a/modules/base/src/test/java/test/com/sun/javafx/binding/ListExpressionHelperTest.java	Tue Sep 22 13:55:16 2015 -0400
+++ b/modules/base/src/test/java/test/com/sun/javafx/binding/ListExpressionHelperTest.java	Wed Sep 23 12:55:26 2015 +0300
@@ -442,6 +442,22 @@
     }
 
     @Test
+    public void testRemoveInvalidation8136465() {
+        helper = ListExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = ListExpressionHelper.addListener(helper, observable, invalidationListener[1]);
+
+        ListExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(observable, 1);
+        invalidationListener[1].check(observable, 1);
+
+        helper = ListExpressionHelper.removeListener(helper, invalidationListener[0]);
+
+        ListExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(observable, 1);
+    }
+
+    @Test
     public void testAddInvalidationWhileLocked() {
         final ChangeListener<Object> addingListener = new ChangeListener() {
             int index = 0;
@@ -591,6 +607,24 @@
     }
 
     @Test
+    public void testRemoveChange8136465() {
+        helper = ListExpressionHelper.addListener(helper, observable, changeListener[0]);
+        helper = ListExpressionHelper.addListener(helper, observable, changeListener[1]);
+
+        observable.set(data2);
+        ListExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(observable, data1, data2, 1);
+        changeListener[1].check(observable, data1, data2, 1);
+
+        helper = ListExpressionHelper.removeListener(helper, changeListener[0]);
+
+        observable.set(data1);
+        ListExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(observable, data2, data1, 1);
+    }
+
+    @Test
     public void testAddChangeWhileLocked() {
         final InvalidationListener addingListener = new InvalidationListener() {
             int index = 0;
@@ -758,6 +792,27 @@
     }
 
     @Test
+    public void testRemoveListChange8136465() {
+        helper = ListExpressionHelper.addListener(helper, observable, listChangeListener[0]);
+        helper = ListExpressionHelper.addListener(helper, observable, listChangeListener[1]);
+
+        observable.set(data2);
+        ListExpressionHelper.fireValueChangedEvent(helper);
+        listChangeListener[0].check1AddRemove(observable, FXCollections.emptyObservableList(), 0, 1);
+        listChangeListener[0].clear();
+        listChangeListener[1].check1AddRemove(observable, FXCollections.emptyObservableList(), 0, 1);
+        listChangeListener[1].clear();
+
+        helper = ListExpressionHelper.removeListener(helper, listChangeListener[0]);
+
+        observable.set(data1);
+        ListExpressionHelper.fireValueChangedEvent(helper);
+        listChangeListener[0].check0();
+        listChangeListener[1].check1AddRemove(observable, FXCollections.singletonObservableList(listItem), 0, 0);
+        listChangeListener[1].clear();
+    }
+
+    @Test
     public void testAddListChangeWhileLocked() {
         final InvalidationListener addingListener = new InvalidationListener() {
             int index = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/base/src/test/java/test/com/sun/javafx/binding/MapExpressionHelperTest.java	Wed Sep 23 12:55:26 2015 +0300
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.com.sun.javafx.binding;
+
+import com.sun.javafx.binding.MapExpressionHelper;
+import javafx.beans.property.MapProperty;
+import javafx.beans.property.SimpleMapProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableMap;
+import org.junit.Before;
+import org.junit.Test;
+import test.javafx.beans.InvalidationListenerMock;
+import test.javafx.beans.value.ChangeListenerMock;
+import test.javafx.collections.MockMapObserver;
+
+public class MapExpressionHelperTest {
+    private static final ObservableMap<Object, Object> UNDEFINED = null;
+    private Object key;
+    private Object value;
+    private ObservableMap<Object, Object> data1;
+    private ObservableMap<Object, Object> data2;
+
+    private MapExpressionHelper helper;
+    private MapProperty<Object, Object> observable;
+
+    private InvalidationListenerMock[] invalidationListener;
+    private ChangeListenerMock<? super ObservableMap<Object, Object>>[] changeListener;
+    private MockMapObserver<Object, Object>[] mapChangeListener;
+
+    @Before
+    public void setUp() {
+        key = new Object();
+        value = new Object();
+        data1 = FXCollections.observableHashMap();
+        data2 = FXCollections.observableHashMap();
+        data2.put(key, value);
+
+        helper = null;
+        observable = new SimpleMapProperty<>(data1);
+
+        invalidationListener = new InvalidationListenerMock[]{
+            new InvalidationListenerMock(), new InvalidationListenerMock(), new InvalidationListenerMock()
+        };
+        changeListener = new ChangeListenerMock[]{
+            new ChangeListenerMock(UNDEFINED), new ChangeListenerMock(UNDEFINED), new ChangeListenerMock(UNDEFINED)
+        };
+        mapChangeListener = new MockMapObserver[]{
+            new MockMapObserver<>(), new MockMapObserver<>(), new MockMapObserver<>()
+        };
+    }
+
+    @Test
+    public void testRemoveInvalidation() {
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[0]);
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[0]);
+
+        helper = MapExpressionHelper.removeListener(helper, invalidationListener[1]);
+
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+
+        helper = MapExpressionHelper.removeListener(helper, invalidationListener[1]);
+
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[2]);
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[1]);
+
+        helper = MapExpressionHelper.removeListener(helper, invalidationListener[0]);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(observable, 1);
+        invalidationListener[2].check(observable, 1);
+
+        helper = MapExpressionHelper.removeListener(helper, invalidationListener[1]);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(null, 0);
+        invalidationListener[2].check(observable, 1);
+
+        helper = MapExpressionHelper.removeListener(helper, invalidationListener[2]);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(null, 0);
+        invalidationListener[2].check(null, 0);
+    }
+
+    @Test
+    public void testRemoveInvalidation8136465() {
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[1]);
+
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(observable, 1);
+        invalidationListener[1].check(observable, 1);
+
+        helper = MapExpressionHelper.removeListener(helper, invalidationListener[0]);
+
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(observable, 1);
+    }
+
+    @Test
+    public void testRemoveChange() {
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[0]);
+
+        helper = MapExpressionHelper.removeListener(helper, changeListener[1]);
+
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[0]);
+
+        helper = MapExpressionHelper.removeListener(helper, changeListener[1]);
+
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[2]);
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[1]);
+
+        helper = MapExpressionHelper.removeListener(helper, changeListener[0]);
+        observable.set(data2);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(observable, data1, data2, 1);
+        changeListener[2].check(observable, data1, data2, 1);
+
+        helper = MapExpressionHelper.removeListener(helper, changeListener[1]);
+        observable.set(data1);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[2].check(observable, data2, data1, 1);
+
+        helper = MapExpressionHelper.removeListener(helper, changeListener[2]);
+        observable.set(data2);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[2].check(null, UNDEFINED, UNDEFINED, 0);
+    }
+
+    @Test
+    public void testRemoveChange8136465() {
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[0]);
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[1]);
+
+        observable.set(data2);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(observable, data1, data2, 1);
+        changeListener[1].check(observable, data1, data2, 1);
+
+        helper = MapExpressionHelper.removeListener(helper, changeListener[0]);
+
+        observable.set(data1);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(observable, data2, data1, 1);
+    }
+
+    @Test
+    public void testRemoveMapChange() {
+        helper = MapExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = MapExpressionHelper.addListener(helper, observable, changeListener[0]);
+
+        helper = MapExpressionHelper.removeListener(helper, mapChangeListener[1]);
+
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[0]);
+
+        helper = MapExpressionHelper.removeListener(helper, mapChangeListener[1]);
+
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[2]);
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[1]);
+
+        helper = MapExpressionHelper.removeListener(helper, mapChangeListener[0]);
+        observable.set(data2);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        mapChangeListener[0].check0();
+        mapChangeListener[1].assertAdded(MockMapObserver.Tuple.tup(key, value));
+        mapChangeListener[1].clear();
+        mapChangeListener[2].assertAdded(MockMapObserver.Tuple.tup(key, value));
+        mapChangeListener[2].clear();
+
+        helper = MapExpressionHelper.removeListener(helper, mapChangeListener[1]);
+        observable.set(data1);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        mapChangeListener[0].check0();
+        mapChangeListener[1].check0();
+        mapChangeListener[2].assertRemoved(MockMapObserver.Tuple.tup(key, value));
+        mapChangeListener[2].clear();
+
+        helper = MapExpressionHelper.removeListener(helper, mapChangeListener[2]);
+        observable.set(data2);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        mapChangeListener[0].check0();
+        mapChangeListener[1].check0();
+        mapChangeListener[2].check0();
+    }
+
+    @Test
+    public void testRemoveMapChange8136465() {
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[0]);
+        helper = MapExpressionHelper.addListener(helper, observable, mapChangeListener[1]);
+
+        observable.set(data2);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        mapChangeListener[0].assertAdded(MockMapObserver.Tuple.tup(key, value));
+        mapChangeListener[0].clear();
+        mapChangeListener[1].assertAdded(MockMapObserver.Tuple.tup(key, value));
+        mapChangeListener[1].clear();
+
+        helper = MapExpressionHelper.removeListener(helper, mapChangeListener[0]);
+
+        observable.set(data1);
+        MapExpressionHelper.fireValueChangedEvent(helper);
+        mapChangeListener[0].check0();
+        mapChangeListener[1].assertRemoved(MockMapObserver.Tuple.tup(key, value));
+        mapChangeListener[1].clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/base/src/test/java/test/com/sun/javafx/binding/SetExpressionHelperTest.java	Wed Sep 23 12:55:26 2015 +0300
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.com.sun.javafx.binding;
+
+import com.sun.javafx.binding.SetExpressionHelper;
+import javafx.beans.property.SetProperty;
+import javafx.beans.property.SimpleSetProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableSet;
+import org.junit.Before;
+import org.junit.Test;
+import test.javafx.beans.InvalidationListenerMock;
+import test.javafx.beans.value.ChangeListenerMock;
+import test.javafx.collections.MockSetObserver;
+
+public class SetExpressionHelperTest {
+    private static final ObservableSet<Object> UNDEFINED = null;
+    private Object value;
+    private ObservableSet<Object> data1;
+    private ObservableSet<Object> data2;
+
+    private SetExpressionHelper helper;
+    private SetProperty<Object> observable;
+
+    private InvalidationListenerMock[] invalidationListener;
+    private ChangeListenerMock<? super ObservableSet<Object>>[] changeListener;
+    private MockSetObserver<Object>[] setChangeListener;
+
+    @Before
+    public void setUp() {
+        value = new Object();
+        data1 = FXCollections.observableSet();
+        data2 = FXCollections.observableSet(value);
+
+        helper = null;
+        observable = new SimpleSetProperty<>(data1);
+
+        invalidationListener = new InvalidationListenerMock[]{
+            new InvalidationListenerMock(), new InvalidationListenerMock(), new InvalidationListenerMock()
+        };
+        changeListener = new ChangeListenerMock[]{
+            new ChangeListenerMock(UNDEFINED), new ChangeListenerMock(UNDEFINED), new ChangeListenerMock(UNDEFINED)
+        };
+        setChangeListener = new MockSetObserver[]{
+            new MockSetObserver<>(), new MockSetObserver<>(), new MockSetObserver<>()
+        };
+    }
+
+    @Test
+    public void testRemoveInvalidation() {
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[0]);
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[0]);
+
+        helper = SetExpressionHelper.removeListener(helper, invalidationListener[1]);
+
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+
+        helper = SetExpressionHelper.removeListener(helper, invalidationListener[1]);
+
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[2]);
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[1]);
+
+        helper = SetExpressionHelper.removeListener(helper, invalidationListener[0]);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(observable, 1);
+        invalidationListener[2].check(observable, 1);
+
+        helper = SetExpressionHelper.removeListener(helper, invalidationListener[1]);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(null, 0);
+        invalidationListener[2].check(observable, 1);
+
+        helper = SetExpressionHelper.removeListener(helper, invalidationListener[2]);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(null, 0);
+        invalidationListener[2].check(null, 0);
+    }
+
+    @Test
+    public void testRemoveInvalidation8136465() {
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[1]);
+
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(observable, 1);
+        invalidationListener[1].check(observable, 1);
+
+        helper = SetExpressionHelper.removeListener(helper, invalidationListener[0]);
+
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        invalidationListener[0].check(null, 0);
+        invalidationListener[1].check(observable, 1);
+    }
+
+    @Test
+    public void testRemoveChange() {
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[0]);
+
+        helper = SetExpressionHelper.removeListener(helper, changeListener[1]);
+
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[0]);
+
+        helper = SetExpressionHelper.removeListener(helper, changeListener[1]);
+
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[2]);
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[1]);
+
+        helper = SetExpressionHelper.removeListener(helper, changeListener[0]);
+        observable.set(data2);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(observable, data1, data2, 1);
+        changeListener[2].check(observable, data1, data2, 1);
+
+        helper = SetExpressionHelper.removeListener(helper, changeListener[1]);
+        observable.set(data1);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[2].check(observable, data2, data1, 1);
+
+        helper = SetExpressionHelper.removeListener(helper, changeListener[2]);
+        observable.set(data2);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[2].check(null, UNDEFINED, UNDEFINED, 0);
+    }
+
+    @Test
+    public void testRemoveChange8136465() {
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[0]);
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[1]);
+
+        observable.set(data2);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(observable, data1, data2, 1);
+        changeListener[1].check(observable, data1, data2, 1);
+
+        helper = SetExpressionHelper.removeListener(helper, changeListener[0]);
+
+        observable.set(data1);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        changeListener[0].check(null, UNDEFINED, UNDEFINED, 0);
+        changeListener[1].check(observable, data2, data1, 1);
+    }
+
+    @Test
+    public void testRemoveMapChange() {
+        helper = SetExpressionHelper.addListener(helper, observable, invalidationListener[0]);
+        helper = SetExpressionHelper.addListener(helper, observable, changeListener[0]);
+
+        helper = SetExpressionHelper.removeListener(helper, setChangeListener[1]);
+
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[0]);
+
+        helper = SetExpressionHelper.removeListener(helper, setChangeListener[1]);
+
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[2]);
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[1]);
+
+        helper = SetExpressionHelper.removeListener(helper, setChangeListener[0]);
+        observable.set(data2);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        setChangeListener[0].check0();
+        setChangeListener[1].assertAdded(MockSetObserver.Tuple.tup(value));
+        setChangeListener[1].clear();
+        setChangeListener[2].assertAdded(MockSetObserver.Tuple.tup(value));
+        setChangeListener[2].clear();
+
+        helper = SetExpressionHelper.removeListener(helper, setChangeListener[1]);
+        observable.set(data1);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        setChangeListener[0].check0();
+        setChangeListener[1].check0();
+        setChangeListener[2].assertRemoved(MockSetObserver.Tuple.tup(value));
+        setChangeListener[2].clear();
+
+        helper = SetExpressionHelper.removeListener(helper, setChangeListener[2]);
+        observable.set(data2);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        setChangeListener[0].check0();
+        setChangeListener[1].check0();
+        setChangeListener[2].check0();
+    }
+
+    @Test
+    public void testRemoveSetChange8136465() {
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[0]);
+        helper = SetExpressionHelper.addListener(helper, observable, setChangeListener[1]);
+
+        observable.set(data2);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        setChangeListener[0].assertAdded(MockSetObserver.Tuple.tup(value));
+        setChangeListener[0].clear();
+        setChangeListener[1].assertAdded(MockSetObserver.Tuple.tup(value));
+        setChangeListener[1].clear();
+
+        helper = SetExpressionHelper.removeListener(helper, setChangeListener[0]);
+
+        observable.set(data1);
+        SetExpressionHelper.fireValueChangedEvent(helper);
+        setChangeListener[0].check0();
+        setChangeListener[1].assertRemoved(MockSetObserver.Tuple.tup(value));
+        setChangeListener[1].clear();
+    }
+}