You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by eb...@apache.org on 2021/09/12 20:07:23 UTC

[netbeans] branch master updated: [NETBEANS-3196] Fix lazy Node loading when switching from Children.LEAF to another Children instance.

This is an automated email from the ASF dual-hosted git repository.

ebakke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 10ee83e  [NETBEANS-3196] Fix lazy Node loading when switching from Children.LEAF to another Children instance.
10ee83e is described below

commit 10ee83e26eda5327aaac4682f92bac6a9f80d23b
Author: Eirik Bakke <eb...@ultorg.com>
AuthorDate: Fri Oct 4 04:06:28 2019 -0400

    [NETBEANS-3196] Fix lazy Node loading when switching from Children.LEAF to another Children instance.
    
    Added a new unit test which failed before the fix and passes after the fix.
---
 .../openide.nodes/src/org/openide/nodes/Node.java  |   2 +-
 .../src/org/openide/nodes/LazyNodeTest3196.java    | 131 +++++++++++++++++++++
 2 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/platform/openide.nodes/src/org/openide/nodes/Node.java b/platform/openide.nodes/src/org/openide/nodes/Node.java
index 569d57f..c78889e 100644
--- a/platform/openide.nodes/src/org/openide/nodes/Node.java
+++ b/platform/openide.nodes/src/org/openide/nodes/Node.java
@@ -500,7 +500,7 @@ public abstract class Node extends FeatureDescriptor implements Lookup.Provider,
             hierarchy = ch;
             hierarchy.attachTo(Node.this);
 
-            if (wasInited && hierarchy != Children.LEAF) {
+            if (wasInited && !wasLeaf && hierarchy != Children.LEAF) {
                 // init new children if old was inited
                 hierarchy.getNodesCount();
 
diff --git a/platform/openide.nodes/test/unit/src/org/openide/nodes/LazyNodeTest3196.java b/platform/openide.nodes/test/unit/src/org/openide/nodes/LazyNodeTest3196.java
new file mode 100644
index 0000000..deff2ac
--- /dev/null
+++ b/platform/openide.nodes/test/unit/src/org/openide/nodes/LazyNodeTest3196.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.openide.nodes;
+
+import org.netbeans.junit.NbTestCase;
+
+/**
+ * Test for NETBEANS-3196, where calling {@code Children.LEAF.getNodesCount()} (e.g. via
+ * {@code Node.EMPTY.getChildren().getNodesCount()}) will prevent lazy loading from working in
+ * certain cases in the future.
+ */
+public class LazyNodeTest3196 extends NbTestCase {
+    {
+        // Not sure if this is needed, but I saw it in some other tests, so it can't hurt...
+        System.setProperty("org.openide.explorer.VisualizerNode.prefetchCount", "0");
+    }
+
+    public LazyNodeTest3196(String name) {
+        super(name);
+    }
+
+    public void testGetLeafGetNodesCountLazy() throws Exception {
+        assertEquals(0, Children.LEAF.getNodesCount());
+        assertEquals(0, Children.LEAF.getNodesCount(true));
+        assertEquals(0, Node.EMPTY.getChildren().getNodesCount());
+        assertEquals(0, Node.EMPTY.getChildren().getNodesCount(true));
+        MyRootNode rootNode = new MyRootNode();
+        assertEquals(0, rootNode.getChildren().getNodesCount());
+        assertEquals(0, rootNode.getChildren().getNodesCount(true));
+
+        /* After calling getNodesCount() on any Children object, including Children.LEAF,
+        isInitialized should return true. */
+        assertEquals(true, Children.LEAF.isInitialized());
+        assertEquals(true, rootNode.getChildren().isInitialized());
+        /* Bug NETBEANS-3196 used to happen when setChildren() was a called on a Node for which
+        the value was previously Children.LEAF. In this case, setChildren() would immediately
+        initialize the new Children eagerly, rather than allowing lazy expansion. */
+        rootNode.setChildrenExposed(new LazyChildrenImplementation());
+
+        /* We haven't queried the new children at this point, so the Children instance should not
+        be initialized. Prior to the fix for NETBEANS-3196, the test would fail at this point. */
+        assertEquals(false, rootNode.getChildren().isInitialized());
+        assertEquals(false, ((LazyChildrenImplementation) rootNode.getChildren()).getWasEverAdded());
+
+        /* I don't think the optimizedResult parameter makes a difference here. Even
+        getNodesCount(false) will cause keys to be computed. */
+        assertEquals(3, rootNode.getChildren().getNodesCount(true));
+        assertEquals(true, rootNode.getChildren().isInitialized());
+        assertEquals(true, ((LazyChildrenImplementation) rootNode.getChildren()).getWasEverAdded());
+
+        /* Now that there is a real, non-LEAF value for setChildren that was genuinely expanded,
+        the intended behavior of setChildren immediately expanding the new value should still
+        work. */
+        rootNode.setChildrenExposed(new LazyChildrenImplementation());
+        assertEquals(true, rootNode.getChildren().isInitialized());
+        assertEquals(true, ((LazyChildrenImplementation) rootNode.getChildren()).getWasEverAdded());
+    }
+
+    private static final class LazyChildrenImplementation extends Children.Keys<Integer> {
+        boolean added;
+        boolean wasEverAdded;
+
+        public boolean getWasEverAdded() {
+            return wasEverAdded;
+        }
+
+        @Override
+        protected Node[] createNodes(Integer key) {
+            return new Node[] { new LazyChildNode(key)} ;
+        }
+
+        @Override
+        protected void addNotify() {
+            if (added) {
+                throw new AssertionError("Already added");
+            }
+            added = true;
+            wasEverAdded = true;
+            setKeys(new Integer[] {1, 2, 3});
+        }
+
+        @Override
+        protected void removeNotify() {
+            if (!added) {
+                throw new AssertionError("Can't remove; wasn't added yet!");
+            }
+            added = false;
+            setKeys(new Integer[] {});
+        }
+    }
+
+    private static final class MyRootNode extends AbstractNode {
+        public MyRootNode() {
+            super(Children.LEAF);
+        }
+
+        public void setChildrenExposed(final Children ch) {
+            setChildren(ch);
+        }
+    }
+
+    private static final class LazyChildNode extends AbstractNode {
+        private final int key;
+
+        public LazyChildNode(int key) {
+            super(Children.LEAF);
+            this.key = key;
+        }
+
+        public int getKey() {
+            return key;
+        }
+    }
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists