Merge "Convert ShadeViewDifferTest to Kotlin" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6f315fc84d
@@ -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