blob: a8536ed9a71360440782262e8eb603e6b729703f [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/devices/bin/driver_manager/tests/bind_manager_test_base.h"
class MultibindTest : public BindManagerTestBase {};
TEST_F(MultibindTest, MultibindSpec_CompositeMultibindDisabled) {
AddAndOrphanNode("node-a", /* enable_multibind */ false);
AddAndOrphanNode("node-c", /* enable_multibind */ true);
VerifyNoOngoingBind();
// Add composite-a. Since node-c can multibind to composites, there will
// be a request sent to the Driver Index to match it to a composite node spec.
AddCompositeNodeSpec("composite-a", {"node-a", "node-c"});
VerifyBindOngoingWithRequests({{"node-a", 1}, {"node-c", 1}});
AddCompositeNodeSpec_EXPECT_QUEUED("composite-b", {"node-a", "node-c"});
// Complete the ongoing bind. It should kickstart another bind process.
DriverIndexReplyWithComposite("node-c", {{"composite-a", 1}});
DriverIndexReplyWithComposite("node-a", {{"composite-a", 0}});
VerifyCompositeNodeExists(true, "composite-a");
VerifyMultibindNodes({"node-c"});
VerifyBindOngoingWithRequests({{"node-c", 1}});
DriverIndexReplyWithComposite("node-c", {{"composite-a", 0}, {"composite-b", 1}});
VerifyCompositeNodeExists(false, "composite-b");
VerifyNoOngoingBind();
}
TEST_F(MultibindTest, MultibindSpecs_NoOverlapBind) {
AddAndOrphanNode("node-a", /* enable_multibind */ true);
AddAndOrphanNode("node-b", /* enable_multibind */ true);
AddAndOrphanNode("node-c", /* enable_multibind */ true);
AddAndOrphanNode("node-d", /* enable_multibind */ true);
VerifyNoOngoingBind();
// Add composite-a. It should trigger bind all available.
AddCompositeNodeSpec("composite-a", {"node-a", "node-b", "node-d"});
VerifyBindOngoingWithRequests({{"node-a", 1}, {"node-b", 1}, {"node-c", 1}, {"node-d", 1}});
// Match associated nodes to composite-a.
DriverIndexReplyWithComposite("node-a", {{"composite-a", 0}});
DriverIndexReplyWithComposite("node-b", {{"composite-a", 1}});
DriverIndexReplyWithNoMatch("node-c");
DriverIndexReplyWithComposite("node-d", {{"composite-a", 2}});
VerifyMultibindNodes({"node-a", "node-b", "node-d"});
VerifyCompositeNodeExists(true, "composite-a");
VerifyNoOngoingBind();
// Add a spec that shares a node with composite-a. It should trigger bind all available.
AddCompositeNodeSpec("composite-b", {"node-b", "node-c"});
VerifyBindOngoingWithRequests({{"node-a", 1}, {"node-b", 1}, {"node-c", 1}, {"node-d", 1}});
DriverIndexReplyWithComposite("node-a", {{"composite-a", 0}});
DriverIndexReplyWithComposite("node-b", {{"composite-a", 1}, {"composite-b", 0}});
DriverIndexReplyWithComposite("node-c", {{"composite-b", 1}});
DriverIndexReplyWithComposite("node-d", {{"composite-a", 2}});
VerifyCompositeNodeExists(true, "composite-a");
VerifyNoOngoingBind();
}
TEST_F(MultibindTest, MultibindSpecs_OverlapBind) {
AddAndOrphanNode("node-a", /* enable_multibind */ true);
AddAndOrphanNode("node-b", /* enable_multibind */ true);
AddAndOrphanNode("node-c", /* enable_multibind */ true);
AddAndOrphanNode("node-d", /* enable_multibind */ true);
VerifyNoOngoingBind();
// Add composite-a. It should trigger bind all available.
AddCompositeNodeSpec("composite-a", {"node-a", "node-b", "node-d"});
VerifyBindOngoingWithRequests({{"node-a", 1}, {"node-b", 1}, {"node-c", 1}, {"node-d", 1}});
// Add a new spec while the nodes are matched.
DriverIndexReplyWithComposite("node-a", {{"composite-a", 0}});
DriverIndexReplyWithComposite("node-b", {{"composite-a", 1}});
AddCompositeNodeSpec_EXPECT_QUEUED("composite-b", {"node-b", "node-c"});
DriverIndexReplyWithNoMatch("node-c");
DriverIndexReplyWithComposite("node-d", {{"composite-a", 2}});
// We should have a new bind ongoing process.
VerifyBindOngoingWithRequests({{"node-a", 1}, {"node-b", 1}, {"node-c", 1}, {"node-d", 1}});
VerifyMultibindNodes({"node-a", "node-b", "node-d"});
VerifyCompositeNodeExists(true, "composite-a");
// Match the nodes to the composites.
DriverIndexReplyWithComposite("node-a", {{"composite-a", 0}});
DriverIndexReplyWithComposite("node-b", {{"composite-a", 1}, {"composite-b", 0}});
DriverIndexReplyWithNoMatch("node-c");
DriverIndexReplyWithComposite("node-d", {{"composite-a", 2}, {"composite-b", 1}});
VerifyMultibindNodes({"node-a", "node-b", "node-d"});
VerifyCompositeNodeExists(true, "composite-b");
VerifyNoOngoingBind();
}
TEST_F(MultibindTest, AddSpecsThenNodes) {
// Add composite-a and composite-b
AddCompositeNodeSpec("composite-a", {"node-a", "node-b", "node-c"});
AddCompositeNodeSpec("composite-b", {"node-b", "node-d"});
VerifyNoOngoingBind();
AddAndBindNode("node-a", /* enable_multibind */ true);
VerifyBindOngoingWithRequests({{"node-a", 1}});
DriverIndexReplyWithComposite("node-a", {{"composite-a", 0}});
VerifyMultibindNodes({"node-a"});
VerifyNoOngoingBind();
AddAndBindNode("node-b", /* enable_multibind */ true);
VerifyBindOngoingWithRequests({{"node-b", 1}});
DriverIndexReplyWithComposite("node-b", {{"composite-a", 1}, {"composite-b", 0}});
VerifyMultibindNodes({"node-a", "node-b"});
VerifyNoOngoingBind();
AddAndBindNode("node-c", /* enable_multibind */ false);
VerifyBindOngoingWithRequests({{"node-c", 1}});
DriverIndexReplyWithComposite("node-c", {{"composite-a", 2}});
VerifyMultibindNodes({"node-a", "node-b"});
VerifyCompositeNodeExists(true, "composite-a");
VerifyNoOngoingBind();
AddAndBindNode("node-d", /* enable_multibind */ true);
VerifyBindOngoingWithRequests({{"node-d", 1}});
DriverIndexReplyWithComposite("node-d", {{"composite-b", 1}});
VerifyMultibindNodes({"node-a", "node-b", "node-d"});
VerifyCompositeNodeExists(true, "composite-b");
VerifyNoOngoingBind();
}