/** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.litho; import android.util.SparseArray; import com.facebook.litho.testing.testrunner.ComponentsTestRunner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.reflect.Whitebox; import static com.facebook.litho.NodeInfo.FOCUS_SET_FALSE; import static com.facebook.litho.NodeInfo.FOCUS_SET_TRUE; import static com.facebook.litho.NodeInfo.FOCUS_UNSET; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.fail; import static org.junit.Assert.assertTrue; @RunWith(ComponentsTestRunner.class) public class NodeInfoTest { private NodeInfo mNodeInfo; @Before public void setup() { mNodeInfo = NodeInfo.acquire(); } @Test public void testTouchHandler() { EventHandler touchHandler = new EventHandler(null, 1); mNodeInfo.setTouchHandler(touchHandler); assertSame(touchHandler, mNodeInfo.getTouchHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getTouchHandler()); } @Test public void testDispatchPopulateAccessibilityEventHandler() { EventHandler<DispatchPopulateAccessibilityEventEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setDispatchPopulateAccessibilityEventHandler(handler); assertSame(handler, mNodeInfo.getDispatchPopulateAccessibilityEventHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getDispatchPopulateAccessibilityEventHandler()); } @Test public void testOnInitializeAccessibilityEventHandler() { EventHandler<OnInitializeAccessibilityEventEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setOnInitializeAccessibilityEventHandler(handler); assertSame(handler, mNodeInfo.getOnInitializeAccessibilityEventHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getOnInitializeAccessibilityEventHandler()); } @Test public void testOnPopulateAccessibilityEventHandler() { EventHandler<OnPopulateAccessibilityEventEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setOnPopulateAccessibilityEventHandler(handler); assertSame(handler, mNodeInfo.getOnPopulateAccessibilityEventHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getOnPopulateAccessibilityEventHandler()); } @Test public void testOnInitializeAccessibilityNodeInfoHandler() { EventHandler<OnInitializeAccessibilityNodeInfoEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setOnInitializeAccessibilityNodeInfoHandler(handler); assertSame(handler, mNodeInfo.getOnInitializeAccessibilityNodeInfoHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getOnInitializeAccessibilityNodeInfoHandler()); } @Test public void testOnRequestSendAccessibilityEventHandler() { EventHandler<OnRequestSendAccessibilityEventEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setOnRequestSendAccessibilityEventHandler(handler); assertSame(handler, mNodeInfo.getOnRequestSendAccessibilityEventHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getOnRequestSendAccessibilityEventHandler()); } @Test public void testPerformAccessibilityActionHandler() { EventHandler<PerformAccessibilityActionEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setPerformAccessibilityActionHandler(handler); assertSame(handler, mNodeInfo.getPerformAccessibilityActionHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getPerformAccessibilityActionHandler()); } @Test public void testSendAccessibilityEventHandler() { EventHandler<SendAccessibilityEventEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setSendAccessibilityEventHandler(handler); assertSame(handler, mNodeInfo.getSendAccessibilityEventHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getSendAccessibilityEventHandler()); } @Test public void testSendAccessibilityEventUncheckedHandler() { EventHandler<SendAccessibilityEventUncheckedEvent> handler = new EventHandler<>(null, 1); mNodeInfo.setSendAccessibilityEventUncheckedHandler(handler); assertSame(handler, mNodeInfo.getSendAccessibilityEventUncheckedHandler()); mNodeInfo.release(); assertNull(mNodeInfo.getSendAccessibilityEventUncheckedHandler()); } @Test public void testClickHandlerFlag() { mNodeInfo.setClickHandler(new EventHandler(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_CLICK_HANDLER_IS_SET"); } @Test public void testLongClickHandlerFlag() { mNodeInfo.setLongClickHandler(new EventHandler(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_LONG_CLICK_HANDLER_IS_SET"); } @Test public void testContentDescriptionFlag() { mNodeInfo.setContentDescription("test"); testFlagIsSetThenClear(mNodeInfo, "PFLAG_CONTENT_DESCRIPTION_IS_SET"); } @Test public void testDispatchPopulateAccessibilityEventHandlerFlag() { mNodeInfo.setDispatchPopulateAccessibilityEventHandler( new EventHandler<DispatchPopulateAccessibilityEventEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_DISPATCH_POPULATE_ACCESSIBILITY_EVENT_HANDLER_IS_SET"); } @Test public void testOnInitializeAccessibilityEventHandlerFlag() { mNodeInfo.setOnInitializeAccessibilityEventHandler( new EventHandler<OnInitializeAccessibilityEventEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_ON_INITIALIZE_ACCESSIBILITY_EVENT_HANDLER_IS_SET"); } @Test public void testOnPopulateAccessibilityEventHandlerFlag() { mNodeInfo.setOnPopulateAccessibilityEventHandler( new EventHandler<OnPopulateAccessibilityEventEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_ON_POPULATE_ACCESSIBILITY_EVENT_HANDLER_IS_SET"); } @Test public void testOnInitializeAccessibilityNodeInfoHandlerFlag() { mNodeInfo.setOnInitializeAccessibilityNodeInfoHandler( new EventHandler<OnInitializeAccessibilityNodeInfoEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_ON_INITIALIZE_ACCESSIBILITY_NODE_INFO_HANDLER_IS_SET"); } @Test public void testOnRequestSendAccessibilityEventHandlerFlag() { mNodeInfo.setOnRequestSendAccessibilityEventHandler( new EventHandler<OnRequestSendAccessibilityEventEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_ON_REQUEST_SEND_ACCESSIBILITY_EVENT_HANDLER_IS_SET"); } @Test public void testPerformAccessibilityActionHandlerFlag() { mNodeInfo.setPerformAccessibilityActionHandler( new EventHandler<PerformAccessibilityActionEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_PERFORM_ACCESSIBILITY_ACTION_HANDLER_IS_SET"); } @Test public void testSendAccessiblityEventHandlerFlag() { mNodeInfo.setSendAccessibilityEventHandler( new EventHandler<SendAccessibilityEventEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_SEND_ACCESSIBILITY_EVENT_HANDLER_IS_SET"); } @Test public void testSendAccessibilityEventUncheckedHandlerFlag() { mNodeInfo.setSendAccessibilityEventUncheckedHandler( new EventHandler<SendAccessibilityEventUncheckedEvent>(null, 1)); testFlagIsSetThenClear(mNodeInfo, "PFLAG_SEND_ACCESSIBILITY_EVENT_UNCHECKED_HANDLER_IS_SET"); } @Test public void testViewTagsFlag() { mNodeInfo.setViewTags(new SparseArray<>()); testFlagIsSetThenClear(mNodeInfo, "PFLAG_VIEW_TAGS_IS_SET"); } @Test public void testFocusableTrue() { assertEquals(FOCUS_UNSET, mNodeInfo.getFocusState()); mNodeInfo.setFocusable(true); assertEquals(FOCUS_SET_TRUE, mNodeInfo.getFocusState()); mNodeInfo.release(); assertEquals(FOCUS_UNSET, mNodeInfo.getFocusState()); } @Test public void testFocusableFalse() { assertEquals(FOCUS_UNSET, mNodeInfo.getFocusState()); mNodeInfo.setFocusable(false); assertEquals(FOCUS_SET_FALSE, mNodeInfo.getFocusState()); mNodeInfo.release(); assertEquals(FOCUS_UNSET, mNodeInfo.getFocusState()); } @Test public void testRefCountAcquiringReleasedNode() { NodeInfo nodeInfo = NodeInfo.acquire(); nodeInfo.acquireRef(); nodeInfo.release(); nodeInfo.release(); // Now it should be back in the pool. try { nodeInfo.acquireRef(); fail("Acquiring a released to pool reference should have thrown an exception."); } catch (Exception e) { // Expected exception. } // Drain pool of bad NodeInfo instances for subsequent tests. clearNodeInfoPool(); } @Test public void testRefCountDoubleReleasingToPool() { NodeInfo nodeInfo = NodeInfo.acquire(); nodeInfo.acquireRef(); nodeInfo.release(); nodeInfo.release(); // Now it should be back in the pool. try { nodeInfo.release(); fail("Releasing a NodeInfo that is already in the pool."); } catch (Exception e) { // Expected exception. } // Drain pool of bad NodeInfo instances for subsequent tests. clearNodeInfoPool(); } private static void testFlagIsSetThenClear(NodeInfo nodeInfo, String flagName) { assertTrue(isFlagSet(nodeInfo, flagName)); clearFlag(nodeInfo, flagName); assertEmptyFlags(nodeInfo); } private static boolean isFlagSet(NodeInfo nodeInfo, String flagName) { int flagPosition = Whitebox.getInternalState(NodeInfo.class, flagName); int flags = Whitebox.getInternalState(nodeInfo, "mPrivateFlags"); return ((flags & flagPosition) != 0); } private static void clearFlag(NodeInfo nodeInfo, String flagName) { int flagPosition = Whitebox.getInternalState(NodeInfo.class, flagName); int flags = Whitebox.getInternalState(nodeInfo, "mPrivateFlags"); flags &= ~flagPosition; Whitebox.setInternalState(nodeInfo, "mPrivateFlags", flags); } private static void assertEmptyFlags(NodeInfo nodeInfo) { assertTrue(((int) Whitebox.getInternalState(nodeInfo, "mPrivateFlags")) == 0); } private static void clearNodeInfoPool() { final RecyclePool<NodeInfo> nodeInfoPool = Whitebox.getInternalState(ComponentsPools.class, "sNodeInfoPool"); while (nodeInfoPool.acquire() != null) { // Run. } } }