diff options
2 files changed, 234 insertions, 317 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.java deleted file mode 100644 index ab712649a90f..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed 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 com.android.systemui.statusbar.notification.collection.render; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import android.content.Context; -import android.testing.AndroidTestingRunner; -import android.view.View; -import android.widget.FrameLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.test.filters.SmallTest; - -import com.android.systemui.SysuiTestCase; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.List; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -public class ShadeViewDifferTest extends SysuiTestCase { - private ShadeViewDiffer mDiffer; - - private FakeController mRootController = new FakeController(mContext, "RootController"); - private FakeController mController1 = new FakeController(mContext, "Controller1"); - private FakeController mController2 = new FakeController(mContext, "Controller2"); - private FakeController mController3 = new FakeController(mContext, "Controller3"); - private FakeController mController4 = new FakeController(mContext, "Controller4"); - private FakeController mController5 = new FakeController(mContext, "Controller5"); - private FakeController mController6 = new FakeController(mContext, "Controller6"); - private FakeController mController7 = new FakeController(mContext, "Controller7"); - - @Mock - ShadeViewDifferLogger mLogger; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mDiffer = new ShadeViewDiffer(mRootController, mLogger); - } - - @Test - public void testAddInitialViews() { - // WHEN a spec is applied to an empty root - // THEN the final tree matches the spec - applySpecAndCheck( - node(mController1), - node(mController2, - node(mController3), - node(mController4) - ), - node(mController5) - ); - } - - @Test - public void testDetachViews() { - // GIVEN a preexisting tree of controllers - applySpecAndCheck( - node(mController1), - node(mController2, - node(mController3), - node(mController4) - ), - node(mController5) - ); - - // WHEN the new spec removes nodes - // THEN the final tree matches the spec - applySpecAndCheck( - node(mController5) - ); - } - - @Test - public void testReparentChildren() { - // GIVEN a preexisting tree of controllers - applySpecAndCheck( - node(mController1), - node(mController2, - node(mController3), - node(mController4) - ), - node(mController5) - ); - - // WHEN the parents of the controllers are all shuffled around - // THEN the final tree matches the spec - applySpecAndCheck( - node(mController1), - node(mController4), - node(mController3, - node(mController2) - ) - ); - } - - @Test - public void testReorderChildren() { - // GIVEN a preexisting tree of controllers - applySpecAndCheck( - node(mController1), - node(mController2), - node(mController3), - node(mController4) - ); - - // WHEN the children change order - // THEN the final tree matches the spec - applySpecAndCheck( - node(mController3), - node(mController2), - node(mController4), - node(mController1) - ); - } - - @Test - public void testRemovedGroupsAreBrokenApart() { - // GIVEN a preexisting tree with a group - applySpecAndCheck( - node(mController1), - node(mController2, - node(mController3), - node(mController4), - node(mController5) - ) - ); - - // WHEN the new spec removes the entire group - applySpecAndCheck( - node(mController1) - ); - - // THEN the group children are no longer attached to their parent - assertNull(mController3.getView().getParent()); - assertNull(mController4.getView().getParent()); - assertNull(mController5.getView().getParent()); - } - - @Test - public void testUnmanagedViews() { - // GIVEN a preexisting tree of controllers - applySpecAndCheck( - node(mController1), - node(mController2, - node(mController3), - node(mController4) - ), - node(mController5) - ); - - // GIVEN some additional unmanaged views attached to the tree - View unmanagedView1 = new View(mContext); - View unmanagedView2 = new View(mContext); - - mRootController.getView().addView(unmanagedView1, 1); - mController2.getView().addView(unmanagedView2, 0); - - // WHEN a new spec is applied with additional nodes - // THEN the final tree matches the spec - applySpecAndCheck( - node(mController1), - node(mController2, - node(mController3), - node(mController4), - node(mController6) - ), - node(mController5), - node(mController7) - ); - - // THEN the unmanaged views have been pushed to the end of their parents - assertEquals(unmanagedView1, mRootController.view.getChildAt(4)); - assertEquals(unmanagedView2, mController2.view.getChildAt(3)); - } - - private void applySpecAndCheck(NodeSpec spec) { - mDiffer.applySpec(spec); - checkMatchesSpec(spec); - } - - private void applySpecAndCheck(SpecBuilder... children) { - applySpecAndCheck(node(mRootController, children).build()); - } - - private void checkMatchesSpec(NodeSpec spec) { - final NodeController parent = spec.getController(); - final List<NodeSpec> children = spec.getChildren(); - - for (int i = 0; i < children.size(); i++) { - NodeSpec childSpec = children.get(i); - View view = parent.getChildAt(i); - - assertEquals( - "Child " + i + " of parent " + parent.getNodeLabel() + " should be " - + childSpec.getController().getNodeLabel() + " but is instead " - + (view != null ? mDiffer.getViewLabel(view) : "null"), - view, - childSpec.getController().getView()); - - if (!childSpec.getChildren().isEmpty()) { - checkMatchesSpec(childSpec); - } - } - } - - private static class FakeController implements NodeController { - - public final FrameLayout view; - private final String mLabel; - - FakeController(Context context, String label) { - view = new FrameLayout(context); - mLabel = label; - } - - @NonNull - @Override - public String getNodeLabel() { - return mLabel; - } - - @NonNull - @Override - public FrameLayout getView() { - return view; - } - - @Override - public int getChildCount() { - return view.getChildCount(); - } - - @Override - public View getChildAt(int index) { - return view.getChildAt(index); - } - - @Override - public void addChildAt(@NonNull NodeController child, int index) { - view.addView(child.getView(), index); - } - - @Override - public void moveChildTo(@NonNull NodeController child, int index) { - view.removeView(child.getView()); - view.addView(child.getView(), index); - } - - @Override - public void removeChild(@NonNull NodeController child, boolean isTransfer) { - view.removeView(child.getView()); - } - - @Override - public void onViewAdded() { - } - - @Override - public void onViewMoved() { - } - - @Override - public void onViewRemoved() { - } - } - - private static class SpecBuilder { - private final NodeController mController; - private final SpecBuilder[] mChildren; - - SpecBuilder(NodeController controller, SpecBuilder... children) { - mController = controller; - mChildren = children; - } - - public NodeSpec build() { - return build(null); - } - - public NodeSpec build(@Nullable NodeSpec parent) { - final NodeSpecImpl spec = new NodeSpecImpl(parent, mController); - for (SpecBuilder childBuilder : mChildren) { - spec.getChildren().add(childBuilder.build(spec)); - } - return spec; - } - } - - private static SpecBuilder node(NodeController controller, SpecBuilder... children) { - return new SpecBuilder(controller, children); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt new file mode 100644 index 000000000000..15cf17dbcf86 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed 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 com.android.systemui.statusbar.notification.collection.render + +import android.content.Context +import android.testing.AndroidTestingRunner +import android.view.View +import android.widget.FrameLayout +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.mockito.mock +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class ShadeViewDifferTest : SysuiTestCase() { + private lateinit var differ: ShadeViewDiffer + private val rootController = FakeController(mContext, "RootController") + private val controller1 = FakeController(mContext, "Controller1") + private val controller2 = FakeController(mContext, "Controller2") + private val controller3 = FakeController(mContext, "Controller3") + private val controller4 = FakeController(mContext, "Controller4") + private val controller5 = FakeController(mContext, "Controller5") + private val controller6 = FakeController(mContext, "Controller6") + private val controller7 = FakeController(mContext, "Controller7") + private val logger: ShadeViewDifferLogger = mock() + + @Before + fun setUp() { + differ = ShadeViewDiffer(rootController, logger) + } + + @Test + fun testAddInitialViews() { + // WHEN a spec is applied to an empty root + // THEN the final tree matches the spec + applySpecAndCheck( + node(controller1), + node(controller2, node(controller3), node(controller4)), + node(controller5) + ) + } + + @Test + fun testDetachViews() { + // GIVEN a preexisting tree of controllers + applySpecAndCheck( + node(controller1), + node(controller2, node(controller3), node(controller4)), + node(controller5) + ) + + // WHEN the new spec removes nodes + // THEN the final tree matches the spec + applySpecAndCheck(node(controller5)) + } + + @Test + fun testReparentChildren() { + // GIVEN a preexisting tree of controllers + applySpecAndCheck( + node(controller1), + node(controller2, node(controller3), node(controller4)), + node(controller5) + ) + + // WHEN the parents of the controllers are all shuffled around + // THEN the final tree matches the spec + applySpecAndCheck( + node(controller1), + node(controller4), + node(controller3, node(controller2)) + ) + } + + @Test + fun testReorderChildren() { + // GIVEN a preexisting tree of controllers + applySpecAndCheck( + node(controller1), + node(controller2), + node(controller3), + node(controller4) + ) + + // WHEN the children change order + // THEN the final tree matches the spec + applySpecAndCheck( + node(controller3), + node(controller2), + node(controller4), + node(controller1) + ) + } + + @Test + fun testRemovedGroupsAreBrokenApart() { + // GIVEN a preexisting tree with a group + applySpecAndCheck( + node(controller1), + node(controller2, node(controller3), node(controller4), node(controller5)) + ) + + // WHEN the new spec removes the entire group + applySpecAndCheck(node(controller1)) + + // THEN the group children are no longer attached to their parent + Assert.assertNull(controller3.view.parent) + Assert.assertNull(controller4.view.parent) + Assert.assertNull(controller5.view.parent) + } + + @Test + fun testUnmanagedViews() { + // GIVEN a preexisting tree of controllers + applySpecAndCheck( + node(controller1), + node(controller2, node(controller3), node(controller4)), + node(controller5) + ) + + // GIVEN some additional unmanaged views attached to the tree + val unmanagedView1 = View(mContext) + val unmanagedView2 = View(mContext) + rootController.view.addView(unmanagedView1, 1) + controller2.view.addView(unmanagedView2, 0) + + // WHEN a new spec is applied with additional nodes + // THEN the final tree matches the spec + applySpecAndCheck( + node(controller1), + node(controller2, node(controller3), node(controller4), node(controller6)), + node(controller5), + node(controller7) + ) + + // THEN the unmanaged views have been pushed to the end of their parents + Assert.assertEquals(unmanagedView1, rootController.view.getChildAt(4)) + Assert.assertEquals(unmanagedView2, controller2.view.getChildAt(3)) + } + + private fun applySpecAndCheck(spec: NodeSpec) { + differ.applySpec(spec) + checkMatchesSpec(spec) + } + + private fun applySpecAndCheck(vararg children: SpecBuilder) { + applySpecAndCheck(node(rootController, *children).build()) + } + + private fun checkMatchesSpec(spec: NodeSpec) { + val parent = spec.controller + val children = spec.children + for (i in children.indices) { + val childSpec = children[i] + val view = parent.getChildAt(i) + Assert.assertEquals( + "Child $i of parent ${parent.nodeLabel} " + + "should be ${childSpec.controller.nodeLabel} " + + "but instead " + + view?.let(differ::getViewLabel), + view, + childSpec.controller.view + ) + if (childSpec.children.isNotEmpty()) { + checkMatchesSpec(childSpec) + } + } + } + + private class FakeController(context: Context, label: String) : NodeController { + override val view: FrameLayout = FrameLayout(context) + override val nodeLabel: String = label + override fun getChildCount(): Int = view.childCount + + override fun getChildAt(index: Int): View? { + return view.getChildAt(index) + } + + override fun addChildAt(child: NodeController, index: Int) { + view.addView(child.view, index) + } + + override fun moveChildTo(child: NodeController, index: Int) { + view.removeView(child.view) + view.addView(child.view, index) + } + + override fun removeChild(child: NodeController, isTransfer: Boolean) { + view.removeView(child.view) + } + + override fun onViewAdded() {} + override fun onViewMoved() {} + override fun onViewRemoved() {} + } + + private class SpecBuilder( + private val mController: NodeController, + private val children: Array<out SpecBuilder> + ) { + + @JvmOverloads + fun build(parent: NodeSpec? = null): NodeSpec { + val spec = NodeSpecImpl(parent, mController) + for (childBuilder in children) { + spec.children.add(childBuilder.build(spec)) + } + return spec + } + } + + companion object { + private fun node(controller: NodeController, vararg children: SpecBuilder): SpecBuilder { + return SpecBuilder(controller, children) + } + } +} |