blob: 456a62dfd9e5fca0a8d269abe5bb4b17b99e1627 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "typecd/port_manager.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "typecd/mock_dbus_manager.h"
#include "typecd/mock_ec_util.h"
#include "typecd/mock_port.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrictMock;
namespace typecd {
class PortManagerNotificationTest : public ::testing::Test {
protected:
void SetUp() override {
// Create a DBusObject.
dbus_object_ = std::make_unique<brillo::dbus_utils::DBusObject>(
nullptr, nullptr, dbus::ObjectPath(kTypecdServicePath));
// Create PortManager, MockPort and MockDBusManager instances.
port_manager_ = std::make_unique<PortManager>();
dbus_manager_ =
std::make_unique<StrictMock<MockDBusManager>>(dbus_object_.get());
port_ = std::make_unique<MockPort>(base::FilePath("fakepath"), 0);
ec_util_ = std::make_unique<MockECUtil>();
// Expect |port_manager_| to execute the RunModeEntry guards.
EXPECT_CALL(*port_, GetDataRole())
.WillRepeatedly(testing::Return(DataRole::kHost));
EXPECT_CALL(*port_, IsPartnerDiscoveryComplete())
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, IsCableDiscoveryComplete())
.WillRepeatedly(testing::Return(true));
}
public:
std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
std::unique_ptr<PortManager> port_manager_;
std::unique_ptr<MockDBusManager> dbus_manager_;
std::unique_ptr<MockPort> port_;
std::unique_ptr<MockECUtil> ec_util_;
};
// Test case for notifications during AP mode entry.
// Port enters USB4 and sends DeviceConnectedType::kThunderboltDp.
// - OWC TBT4 dock and Caldigit TBT4 cable.
TEST_F(PortManagerNotificationTest, ModeEntryUSB4NotifyThunderboltDp) {
// Add OWC TBT4 dock and Caldigit TBT4 cable.
AddOWCTBT4Dock(*port_);
AddCalDigitTBT4Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter USB4.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kUSB4))
.WillRepeatedly(testing::Return(true));
// Expect to send DeviceConnectedType::kThunderboltDp.
EXPECT_CALL(*dbus_manager_,
NotifyConnected(DeviceConnectedType::kThunderboltDp))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters TBT and sends DeviceConnectedType::kThunderboltOnly.
// - Startech TB3DK2DPW dock and Caldigit TBT4 cable.
TEST_F(PortManagerNotificationTest, ModeEntryTBTNotifyThunderboltOnly) {
// Add Startech TB3DK2DPW dock and Caldigit TBT4 cable.
AddStartechTB3DK2DPWDock(*port_);
AddCalDigitTBT4Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter TBT.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(false));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kTBT))
.WillRepeatedly(testing::Return(true));
// Expect to send DeviceConnectedType::kThunderboltOnly.
EXPECT_CALL(*dbus_manager_,
NotifyConnected(DeviceConnectedType::kThunderboltOnly))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters DP and sends no notifications.
// - Wimaxit display and Caldigit TBT4 cable.
TEST_F(PortManagerNotificationTest, ModeEntryDpAltModeNoNotifications) {
// Add Wimaxit display and Caldigit TBT4 cable.
AddWimaxitDisplay(*port_);
AddCalDigitTBT4Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter DP.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kDP))
.WillRepeatedly(testing::Return(true));
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters USB4 and sends DeviceConnectedType::kThunderboltDp and
// CableWarningType::kSpeedLimitingCable.
// - OWC TBT4 dock with Anker USB 3.2 Gen2 cable.
TEST_F(PortManagerNotificationTest, ModeEntryUSB4NotifySpeedLimitingCable) {
// Add OWC TBT4 dock with Anker USB 3.2 Gen2 cable.
AddOWCTBT4Dock(*port_);
AddAnkerUSB3p2Gen2Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter USB4.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kUSB4))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, CableLimitingUSBSpeed(false))
.WillRepeatedly(testing::Return(true));
// Expect to send DeviceConnectedType::kThunderboltDp and
// CableWarningType::kSpeedLimitingCable.
EXPECT_CALL(*dbus_manager_,
NotifyConnected(DeviceConnectedType::kThunderboltDp))
.Times(1);
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kSpeedLimitingCable))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters TBT and sends DeviceConnectedType::kThunderboltDp and
// CableWarningType::kSpeedLimitingCable.
// - Thinkpad TBT3 dock and Anker USB 3.2 Gen2 passive cable.
TEST_F(PortManagerNotificationTest, ModeEntryTBTNotifySpeedLimitingCable) {
// Add Thinkpad TBT3 Dock and Anker USB 3.2 Gen2 passive cable.
AddThinkpadTBT3Dock(*port_);
AddAnkerUSB3p2Gen2Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter TBT.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kTBT))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, CableLimitingUSBSpeed(true))
.WillRepeatedly(testing::Return(true));
// Expect to send DeviceConnectedType::kThunderboltDp and
// CableWarningType::kSpeedLimitingCable.
EXPECT_CALL(*dbus_manager_,
NotifyConnected(DeviceConnectedType::kThunderboltDp))
.Times(1);
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kSpeedLimitingCable))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters TBT and sends DeviceConnectedType::kThunderboltDp and
// CableWarningType::kInvalidUSB4ValidTBTCable.
// - OWC TBT4 dock and Belkin TBT3 active cable.
TEST_F(PortManagerNotificationTest,
ModeEntryTBTNotifyInvalidUSB4ValidTBTCable) {
// Add OWC TBT4 dock and Belkin TBT3 active cable.
AddOWCTBT4Dock(*port_);
AddBelkinTBT3ActiveCable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter TBT.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kSuccess));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kCableError));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kTBT))
.WillRepeatedly(testing::Return(true));
// Expect to send DeviceConnectedType::kThunderboltDp and
// CableWarningType::kInvalidUSB4ValidTBTCable.
EXPECT_CALL(*dbus_manager_,
NotifyConnected(DeviceConnectedType::kThunderboltDp))
.Times(1);
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kInvalidUSB4ValidTBTCable))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters DP and sends CableWarningType::kInvalidUSB4Cable).
// - OWC TBT4 dock and unbranded USB 2.0 cable.
TEST_F(PortManagerNotificationTest, ModeEntryDpAltModeNotifyInvalidUSB4Cable) {
// Add OWC TBT4 dock and unbranded USB 2.0 cable.
AddOWCTBT4Dock(*port_);
AddUnbrandedUSB2Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter DP.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kCableError));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kCableError));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kDP))
.WillRepeatedly(testing::Return(true));
// Expect to send CableWarningType::kInvalidUSB4Cable.
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kInvalidUSB4Cable))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters DP and sends CableWarningType::kInvalidTBTCable.
// - Thinkpad TBT3 dock and unbranded USB 2.0 cable.
TEST_F(PortManagerNotificationTest, ModeEntryDpAltModeNotifyInvalidTBTCable) {
// Add Thinkpad TBT3 dock and unbranded USB 2.0 cable.
AddThinkpadTBT3Dock(*port_);
AddUnbrandedUSB2Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter DP.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kCableError));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kDP))
.WillRepeatedly(testing::Return(true));
// Expect to send CableWarningType::kInvalidTBTCable.
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kInvalidTBTCable))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during AP mode entry.
// Port enters DP and sends CableWarningType::kInvalidDpCable.
// - Add Wimaxit display and unbranded USB 2.0 cable.
TEST_F(PortManagerNotificationTest, ModeEntryDpAltModeNotifyInvalidDpCable) {
// Add Wimaxit display and unbranded USB 2.0 cable.
AddWimaxitDisplay(*port_);
AddUnbrandedUSB2Cable(*port_);
// Set AP mode entry to true for test case covering AP driven mode entry.
port_manager_->SetModeEntrySupported(true);
// Set expectations for port to enter DP.
EXPECT_CALL(*port_, CanEnterTBTCompatibilityMode())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*port_, CanEnterUSB4())
.WillRepeatedly(testing::Return(ModeEntryResult::kPartnerError));
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(true), testing::Return(true)));
EXPECT_CALL(*ec_util_, EnterMode(0, TypeCMode::kDP))
.WillRepeatedly(testing::Return(true));
// Expect to send CableWarningType::kInvalidDpCable
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kInvalidDpCable))
.Times(1);
// Configure |port_manager_| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during EC mode entry.
// Port does not enter mode, or send any notifications.
// - OWC TBT4 dock and Caldigit TBT4 cable.
TEST_F(PortManagerNotificationTest, ECModeEntryNoCableNotification) {
// Add OWC TBT4 dock and Caldigit TBT4 cable.
AddOWCTBT4Dock(*port_);
AddCalDigitTBT4Cable(*port_);
// Set AP mode entry to false for test case covering EC driven mode entry.
port_manager_->SetModeEntrySupported(false);
// Expect |port_manager| to check for cable notifications. This happens
// when GetModeEntrySupported returns false.
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillOnce(DoAll(SetArgPointee<0>(false), Return(true)));
// Configure |port_manager| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during EC mode entry.
// Port does not enter a mode, but sends CableWarningType::kInvalidDpCable.
// - OWC TBT4 dock and unbranded USB 2.0 cable.
TEST_F(PortManagerNotificationTest, ECModeEntryNotifyInvalidDpCable) {
// Add OWC TBT4 dock and unbranded USB 2.0 cable.
AddOWCTBT4Dock(*port_);
AddUnbrandedUSB2Cable(*port_);
// Set AP mode entry to false for test case covering EC driven mode entry.
port_manager_->SetModeEntrySupported(false);
// Expect |port_manager| to check for cable notifications. This happens
// when GetModeEntrySupported returns false.
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(true), Return(true)));
// Expect to send CableWarningType::kInvalidDpCable.
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kInvalidDpCable))
.Times(1);
// Configure |port_manager| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
// Test case for notifications during EC mode entry.
// Port does not enter a mode, but sends CableWarningType::kInvalidDpCable.
// - OWC TBT4 dock and emarked USB 2.0 cable.
TEST_F(PortManagerNotificationTest, ECModeEntryNotifyInvalidDpCableEmarked) {
// Add OWC TBT4 dock and emarked USB 2.0 cable.
AddOWCTBT4Dock(*port_);
AddNekteckUSB2PassiveCable(*port_);
// Set AP mode entry to false for test case covering EC driven mode entry.
port_manager_->SetModeEntrySupported(false);
// Expect |port_manager| to check for cable notifications. This happens
// when GetModeEntrySupported returns false.
EXPECT_CALL(*port_, CanEnterDPAltMode(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(true), Return(true)));
// Expect to send CableWarningType::kInvalidDpCable.
EXPECT_CALL(*dbus_manager_,
NotifyCableWarning(CableWarningType::kInvalidDpCable))
.Times(1);
// Configure |port_manager| and run mode entry.
port_manager_->SetUserActive(true);
port_manager_->SetDBusManager(dbus_manager_.get());
port_manager_->SetECUtil(ec_util_.get());
port_manager_->ports_.insert(
std::pair<int, std::unique_ptr<Port>>(0, std::move(port_)));
port_manager_->RunModeEntry(0);
}
} // namespace typecd