Merge "Convert ShadeViewDifferTest to Kotlin" into tm-qpr-dev am: 6f315fc84d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20310724 Change-Id: Ib8c1cf00714df578234bc0eedee97baae8be7cb8 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user