blob: 88baa7580f698038cf5df4c40b16c6dba079fa05 [file] [log] [blame]
// Copyright 2015 The Chromium 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 "media/midi/midi_manager_alsa.h"
#include <memory>
#include <utility>
#include "testing/gtest/include/gtest/gtest.h"
namespace midi {
class MidiManagerAlsaTest : public ::testing::Test {
protected:
void SetUp() override {
// Pre-instantiate typical MidiPort instances that are often used in
// following tests.
// Inputs. port_input_0_ == port_input_1_.
port_input_0_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_1_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_minimal_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 0, 0, 0, "", "", "", "",
MidiManagerAlsa::MidiPort::Type::kInput));
// Outputs. port_output_0_ == port_output_1_.
port_output_0_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kOutput));
port_output_1_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kOutput));
// MidiPort fields that differ from port_input_0_ in a single way each time.
// Used for testing the Match* and Find* methods.
port_input_0_alt_path_.reset(new MidiManagerAlsa::MidiPort(
"path2", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_alt_id_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial2"),
1, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_alt_client_name_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name2", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_alt_port_name_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 5, "client_name", "port_name2", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_alt_client_id_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
2, 2, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_alt_port_id_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 3, 5, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_alt_midi_device_.reset(new MidiManagerAlsa::MidiPort(
"path", MidiManagerAlsa::MidiPort::Id("bus", "vendor", "model",
"interface", "serial"),
1, 2, 6, "client_name", "port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
// "No card" variants of above. For testing FindDisconnected.
port_input_0_no_card_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 1, 2, -1, "client_name",
"port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_1_no_card_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 1, 2, -1, "client_name",
"port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_output_0_no_card_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 1, 2, -1, "client_name",
"port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kOutput));
// No card variants of the alt variants from above. For more testing
// of Match* and Find*.
port_input_0_no_card_alt_client_name_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 1, 2, -1, "client_name2",
"port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_no_card_alt_port_name_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 1, 2, -1, "client_name",
"port_name2", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_no_card_alt_client_id_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 2, 2, -1, "client_name",
"port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
port_input_0_no_card_alt_port_id_.reset(new MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 1, 3, -1, "client_name",
"port_name", "manufacturer", "version",
MidiManagerAlsa::MidiPort::Type::kInput));
}
// Counts ports for help with testing ToMidiPortState().
int CountPorts(MidiManagerAlsa::TemporaryMidiPortState& state) {
int count = 0;
for (auto it = state.begin(); it != state.end(); ++it)
++count;
return count;
}
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_1_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_minimal_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_output_0_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_output_1_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_path_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_id_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_client_name_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_port_name_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_client_id_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_port_id_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_alt_midi_device_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_no_card_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_1_no_card_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_output_0_no_card_;
std::unique_ptr<MidiManagerAlsa::MidiPort>
port_input_0_no_card_alt_client_name_;
std::unique_ptr<MidiManagerAlsa::MidiPort>
port_input_0_no_card_alt_port_name_;
std::unique_ptr<MidiManagerAlsa::MidiPort>
port_input_0_no_card_alt_client_id_;
std::unique_ptr<MidiManagerAlsa::MidiPort> port_input_0_no_card_alt_port_id_;
// State fields to avoid declaring in test fixtures below.
MidiManagerAlsa::MidiPortState midi_port_state_0_;
MidiManagerAlsa::MidiPortState midi_port_state_1_;
MidiManagerAlsa::TemporaryMidiPortState temporary_midi_port_state_0_;
MidiManagerAlsa::AlsaSeqState alsa_seq_state_0_;
MidiManagerAlsa::AlsaCardMap alsa_cards_;
};
// Tests that ExtractManufacturerString works as expected.
TEST_F(MidiManagerAlsaTest, ExtractManufacturer) {
EXPECT_EQ("My\\x20Vendor",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"My\\x20Vendor", "1234", "My Vendor, Inc.", "Card",
"My Vendor Inc Card at bus"));
EXPECT_EQ("My Vendor", MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"My Vendor", "1234", "My Vendor, Inc.", "Card",
"My Vendor Inc Card at bus"));
EXPECT_EQ("My Vendor, Inc.",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"1234", "1234", "My Vendor, Inc.", "Card",
"My Vendor Inc Card at bus"));
EXPECT_EQ("My Vendor Inc",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"1234", "1234", "", "Card", "My Vendor Inc Card at bus"));
EXPECT_EQ("My Vendor Inc",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"", "", "", "Card", "My Vendor Inc Card at bus"));
EXPECT_EQ("", MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"1234", "1234", "", "Card", "Longname"));
EXPECT_EQ("Keystation\\x20Mini\\x2032",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"Keystation\\x20Mini\\x2032", "129d",
"Evolution Electronics, Ltd", "Keystation Mini 32",
"Keystation Mini 32 Keystation Mini 32 at"
" usb-0000:00:14.0-2.4.4, full speed"));
EXPECT_EQ("Keystation Mini 32",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"Keystation Mini 32", "129d", "Evolution Electronics, Ltd",
"Keystation Mini 32",
"Keystation Mini 32 Keystation Mini 32 at"
" usb-0000:00:14.0-2.4.4, full speed"));
EXPECT_EQ("Keystation Mini 32",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"", "", "", "Keystation Mini 32",
"Keystation Mini 32 Keystation Mini 32 at"
" usb-0000:00:14.0-2.4.4, full speed"));
EXPECT_EQ("", MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"", "", "", "Serial MIDI (UART16550A)",
"Serial MIDI (UART16550A) [Soundcanvas] at 0x3f8, irq 4"));
EXPECT_EQ("", MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"", "", "", "VirMIDI", "Virtual MIDI Card 1"));
EXPECT_EQ("C-Media Electronics Inc",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"", "0x13f6", "C-Media Electronics Inc", "C-Media CMI8738 MIDI",
"C-Media CMI8738 (model 55) at 0xd000, irq 19"));
EXPECT_EQ("C-Media Electronics Inc",
MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
"", "0x13f6", "C-Media Electronics Inc", "C-Media CMI8738 FM",
"C-Media CMI8738 (model 55) at 0xd000, irq 19"));
}
// Tests that verify proper serialization and generation of opaque key for
// MidiPort.
TEST_F(MidiManagerAlsaTest, JSONPortMetadata) {
EXPECT_EQ(
"{\"bus\":\"bus\",\"clientId\":1,\"clientName\":\"client_name\","
"\"midiDevice\":5,\"modelId\":\"model\",\"path\":\"path\",\"portId\":2,"
"\"portName\":\"port_name\",\"serial\":\"serial\",\"type\":\"input\","
"\"usbInterfaceNum\":\"interface\",\"vendorId\":\"vendor\"}",
port_input_0_->JSONValue());
EXPECT_EQ("810194DAF713B32FC9BE40EC822E21682635B48C242D09EA95DBA4A184A95877",
port_input_0_->OpaqueKey());
EXPECT_EQ(
"{\"bus\":\"bus\",\"clientId\":1,\"clientName\":\"client_name\","
"\"midiDevice\":5,\"modelId\":\"model\",\"path\":\"path\",\"portId\":2,"
"\"portName\":\"port_name\",\"serial\":\"serial\",\"type\":\"output\","
"\"usbInterfaceNum\":\"interface\",\"vendorId\":\"vendor\"}",
port_output_0_->JSONValue());
EXPECT_EQ("C32552FC772A0CA453A675CED05EFB3BDEF749EB58ED9522475206F111BC01E2",
port_output_0_->OpaqueKey());
EXPECT_EQ("{\"clientId\":0,\"midiDevice\":0,\"portId\":0,\"type\":\"input\"}",
port_input_minimal_->JSONValue());
EXPECT_EQ("3BC2A85598E5026D01DBCB022016C8A3362A9C7F912B88E303BF619C56D0C111",
port_input_minimal_->OpaqueKey());
}
// Tests Match* methods.
TEST_F(MidiManagerAlsaTest, MatchConnected) {
// The query can be disconnected or connected, but the target
// must be connected.
port_input_1_->set_connected(false);
EXPECT_TRUE(port_input_0_->MatchConnected(*port_input_1_.get()));
EXPECT_FALSE(port_input_1_->MatchConnected(*port_input_0_.get()));
// Differing types.
EXPECT_FALSE(port_input_0_->MatchConnected(*port_output_0_.get()));
// Differing in 1 field. None should succeed.
EXPECT_FALSE(port_input_0_->MatchConnected(*port_input_0_alt_path_.get()));
EXPECT_FALSE(port_input_0_->MatchConnected(*port_input_0_alt_id_.get()));
EXPECT_FALSE(
port_input_0_->MatchConnected(*port_input_0_alt_client_name_.get()));
EXPECT_FALSE(
port_input_0_->MatchConnected(*port_input_0_alt_port_name_.get()));
EXPECT_FALSE(
port_input_0_->MatchConnected(*port_input_0_alt_client_id_.get()));
EXPECT_FALSE(port_input_0_->MatchConnected(*port_input_0_alt_port_id_.get()));
EXPECT_FALSE(
port_input_0_->MatchConnected(*port_input_0_alt_midi_device_.get()));
}
TEST_F(MidiManagerAlsaTest, MatchCard1) {
// The query can be disconnected or connected, but the target
// must be disonnected.
EXPECT_FALSE(port_input_0_->MatchCardPass1(*port_input_1_.get()));
port_input_0_->set_connected(false);
EXPECT_TRUE(port_input_0_->MatchCardPass1(*port_input_1_.get()));
// Differing types.
EXPECT_FALSE(port_input_0_->MatchCardPass1(*port_output_0_.get()));
// Tests matches differing in 1 field.
// client_name, port_name, client_id are ok to differ.
EXPECT_FALSE(port_input_0_->MatchCardPass1(*port_input_0_alt_path_.get()));
EXPECT_FALSE(port_input_0_->MatchCardPass1(*port_input_0_alt_id_.get()));
EXPECT_TRUE(
port_input_0_->MatchCardPass1(*port_input_0_alt_client_name_.get()));
EXPECT_TRUE(
port_input_0_->MatchCardPass1(*port_input_0_alt_port_name_.get()));
EXPECT_TRUE(
port_input_0_->MatchCardPass1(*port_input_0_alt_client_id_.get()));
EXPECT_FALSE(port_input_0_->MatchCardPass1(*port_input_0_alt_port_id_.get()));
EXPECT_FALSE(
port_input_0_->MatchCardPass1(*port_input_0_alt_midi_device_.get()));
}
TEST_F(MidiManagerAlsaTest, MatchCard2) {
// The query can be disconnected or connected, but the target
// must be disonnected.
EXPECT_FALSE(port_input_0_->MatchCardPass2(*port_input_1_.get()));
port_input_0_->set_connected(false);
EXPECT_TRUE(port_input_0_->MatchCardPass2(*port_input_1_.get()));
// Differing types.
EXPECT_FALSE(port_input_0_->MatchCardPass2(*port_output_0_.get()));
// Tests matches differing in 1 field.
// client_name, port_name, path, client_id are ok to differ.
EXPECT_TRUE(port_input_0_->MatchCardPass2(*port_input_0_alt_path_.get()));
EXPECT_FALSE(port_input_0_->MatchCardPass2(*port_input_0_alt_id_.get()));
EXPECT_TRUE(
port_input_0_->MatchCardPass2(*port_input_0_alt_client_name_.get()));
EXPECT_TRUE(
port_input_0_->MatchCardPass2(*port_input_0_alt_port_name_.get()));
EXPECT_TRUE(
port_input_0_->MatchCardPass2(*port_input_0_alt_client_id_.get()));
EXPECT_FALSE(port_input_0_->MatchCardPass2(*port_input_0_alt_port_id_.get()));
EXPECT_FALSE(
port_input_0_->MatchCardPass2(*port_input_0_alt_midi_device_.get()));
}
TEST_F(MidiManagerAlsaTest, MatchNoCard1) {
// The query can be disconnected or connected, but the target
// must be disonnected.
// path and id must be empty. midi_device must be -1.
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass1(*port_input_1_.get()));
port_input_0_no_card_->set_connected(false);
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass1(*port_input_1_.get()));
EXPECT_TRUE(
port_input_0_no_card_->MatchNoCardPass1(*port_input_1_no_card_.get()));
// Differing types.
EXPECT_FALSE(
port_input_0_no_card_->MatchNoCardPass1(*port_output_0_no_card_.get()));
// Tests matches differing in 1 field.
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass1(
*port_input_0_no_card_alt_client_name_.get()));
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass1(
*port_input_0_no_card_alt_port_name_.get()));
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass1(
*port_input_0_no_card_alt_client_id_.get()));
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass1(
*port_input_0_no_card_alt_port_id_.get()));
}
TEST_F(MidiManagerAlsaTest, MatchNoCard2) {
// The query can be disconnected or connected, but the target
// must be disonnected.
// path and id must be empty. midi_device must be -1.
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass2(*port_input_1_.get()));
port_input_0_no_card_->set_connected(false);
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass2(*port_input_1_.get()));
EXPECT_TRUE(
port_input_0_no_card_->MatchNoCardPass2(*port_input_1_no_card_.get()));
// Differing types.
EXPECT_FALSE(
port_input_0_no_card_->MatchNoCardPass2(*port_output_0_no_card_.get()));
// Tests matches differing in 1 field.
// client_id ok to differ.
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass2(
*port_input_0_no_card_alt_client_name_.get()));
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass2(
*port_input_0_no_card_alt_port_name_.get()));
EXPECT_TRUE(port_input_0_no_card_->MatchNoCardPass2(
*port_input_0_no_card_alt_client_id_.get()));
EXPECT_FALSE(port_input_0_no_card_->MatchNoCardPass2(
*port_input_0_no_card_alt_port_id_.get()));
}
// Tests that MidiPorts start connected.
TEST_F(MidiManagerAlsaTest, PortStartsConnected) {
EXPECT_TRUE(port_output_0_->connected());
EXPECT_TRUE(port_input_0_->connected());
}
// Tests that the web_port_index gets updated by MidiPortState.
TEST_F(MidiManagerAlsaTest, PortIndexSet) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_output_0_tracking_pointer = port_output_0_.get();
auto* port_input_1_tracking_pointer = port_input_1_.get();
auto* port_output_1_tracking_pointer = port_input_1_.get();
// Explicitly initialize web_port_index.
port_input_1_->set_web_port_index(5000);
port_output_1_->set_web_port_index(5000);
midi_port_state_0_.push_back(std::move(port_input_0_));
midi_port_state_0_.push_back(std::move(port_output_0_));
midi_port_state_0_.push_back(std::move(port_input_1_));
midi_port_state_0_.push_back(std::move(port_output_1_));
// First port of each type has index of 0.
EXPECT_EQ(0U, port_input_0_tracking_pointer->web_port_index());
EXPECT_EQ(0U, port_output_0_tracking_pointer->web_port_index());
// Second port of each type has index of 1.
EXPECT_EQ(1U, port_input_1_tracking_pointer->web_port_index());
EXPECT_EQ(1U, port_output_1_tracking_pointer->web_port_index());
}
// Tests that the web_port_index is not updated by TemporaryMidiPortState.
TEST_F(MidiManagerAlsaTest, PortIndexNotSet) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_output_0_tracking_pointer = port_output_0_.get();
auto* port_input_1_tracking_pointer = port_input_1_.get();
auto* port_output_1_tracking_pointer = port_input_1_.get();
// Explicitly initialize web_port_index.
port_input_1_->set_web_port_index(5000);
port_output_1_->set_web_port_index(5000);
temporary_midi_port_state_0_.push_back(std::move(port_input_0_));
temporary_midi_port_state_0_.push_back(std::move(port_output_0_));
temporary_midi_port_state_0_.push_back(std::move(port_input_1_));
temporary_midi_port_state_0_.push_back(std::move(port_output_1_));
// web_port_index is untouched.
EXPECT_EQ(0U, port_input_0_tracking_pointer->web_port_index());
EXPECT_EQ(0U, port_output_0_tracking_pointer->web_port_index());
EXPECT_EQ(5000U, port_input_1_tracking_pointer->web_port_index());
EXPECT_EQ(5000U, port_output_1_tracking_pointer->web_port_index());
}
// Tests that inputs and outputs stay separate in MidiPortState.
TEST_F(MidiManagerAlsaTest, SeparateInputOutput) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_output_0_tracking_pointer = port_output_0_.get();
auto* port_input_1_tracking_pointer = port_input_1_.get();
auto* port_output_1_tracking_pointer = port_input_1_.get();
// First port of each type has index of 0.
EXPECT_EQ(0U, midi_port_state_0_.push_back(std::move(port_input_0_)));
EXPECT_EQ(0U, midi_port_state_0_.push_back(std::move(port_output_0_)));
// Second port of each type has index of 1.
EXPECT_EQ(1U, midi_port_state_0_.push_back(std::move(port_input_1_)));
EXPECT_EQ(1U, midi_port_state_0_.push_back(std::move(port_output_1_)));
// Check again that the field matches what was returned.
EXPECT_EQ(0U, port_input_0_tracking_pointer->web_port_index());
EXPECT_EQ(0U, port_output_0_tracking_pointer->web_port_index());
EXPECT_EQ(1U, port_input_1_tracking_pointer->web_port_index());
EXPECT_EQ(1U, port_output_1_tracking_pointer->web_port_index());
}
// Tests FindConnected.
TEST_F(MidiManagerAlsaTest, FindConnected) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_input_1_tracking_pointer = port_input_1_.get();
// Insert port_input_0.
midi_port_state_0_.push_back(std::move(port_input_0_));
// Look for port_input_1 (every field matches port_input_0).
auto it = midi_port_state_0_.FindConnected(*port_input_1_tracking_pointer);
EXPECT_EQ(port_input_0_tracking_pointer, it->get());
// Look for something else that we won't find.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindConnected(*port_input_0_alt_path_));
}
TEST_F(MidiManagerAlsaTest, FindConnected2) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_input_1_tracking_pointer = port_input_1_.get();
// Insert some stuff.
midi_port_state_0_.push_back(std::move(port_input_0_alt_path_));
midi_port_state_0_.push_back(std::move(port_input_0_alt_id_));
midi_port_state_0_.push_back(std::move(port_input_0_alt_client_name_));
// Insert port_input_0.
midi_port_state_0_.push_back(std::move(port_input_0_));
// Insert some more stuff.
midi_port_state_0_.push_back(std::move(port_input_0_alt_port_id_));
// Look for port_input_1 (matches to port_input_0).
auto it = midi_port_state_0_.FindConnected(*port_input_1_tracking_pointer);
EXPECT_EQ(port_input_0_tracking_pointer, it->get());
// Look for something else that we won't find.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindConnected(*port_input_minimal_));
}
TEST_F(MidiManagerAlsaTest, FindConnected3) {
// midi_port_state_0_ is empty to start.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindConnected(*port_input_minimal_));
}
// Tests FindDisconnected.
TEST_F(MidiManagerAlsaTest, FindDisconnected) {
// midi_port_state_0_ is empty to start.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindDisconnected(*port_input_minimal_));
}
TEST_F(MidiManagerAlsaTest, FindDisconnected2) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_input_1_tracking_pointer = port_input_1_.get();
auto* port_input_1_no_card_tracking_pointer = port_input_1_no_card_.get();
// Ports need to be disconnected to find them.
port_input_0_alt_id_->set_connected(false);
port_input_0_alt_path_->set_connected(false);
port_input_0_->set_connected(false);
// Insert some stuff.
midi_port_state_0_.push_back(std::move(port_input_0_alt_id_));
midi_port_state_0_.push_back(std::move(port_input_0_alt_path_));
// Insert port_input_0.
midi_port_state_0_.push_back(std::move(port_input_0_));
// Add "no card" stuff.
port_input_1_no_card_->set_connected(false);
midi_port_state_0_.push_back(std::move(port_input_1_no_card_));
// Insert some more stuff.
midi_port_state_0_.push_back(std::move(port_input_0_alt_port_id_));
// Look for port_input_1, should trigger exact match.
EXPECT_EQ(port_input_0_tracking_pointer,
midi_port_state_0_.FindDisconnected(*port_input_1_tracking_pointer)
->get());
// Look for no card exact match.
EXPECT_EQ(
port_input_1_no_card_tracking_pointer,
midi_port_state_0_.FindDisconnected(*port_input_0_no_card_.get())->get());
// Look for something else that we won't find.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindDisconnected(*port_input_minimal_));
}
TEST_F(MidiManagerAlsaTest, FindDisconnected3) {
auto* port_input_0_tracking_pointer = port_input_0_.get();
auto* port_input_0_alt_path_tracking_pointer = port_input_0_alt_path_.get();
auto* port_input_1_no_card_tracking_pointer = port_input_1_no_card_.get();
// Ports need to be disconnected to find them.
port_input_0_alt_path_->set_connected(false);
port_input_0_->set_connected(false);
// Insert some stuff.
midi_port_state_0_.push_back(std::move(port_input_0_alt_path_));
midi_port_state_0_.push_back(std::move(port_input_0_alt_id_));
// Add no card stuff.
port_input_1_no_card_->set_connected(false);
midi_port_state_0_.push_back(std::move(port_input_1_no_card_));
// Look for port_input_0, should find port_input_0_alt_path.
EXPECT_EQ(port_input_0_alt_path_tracking_pointer,
midi_port_state_0_.FindDisconnected(*port_input_0_tracking_pointer)
->get());
// Look for no card partial match.
EXPECT_EQ(port_input_1_no_card_tracking_pointer,
midi_port_state_0_.FindDisconnected(
*port_input_0_no_card_alt_client_id_.get())
->get());
// Won't find this.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindDisconnected(
*port_input_0_no_card_alt_port_id_.get()));
// Look for something else that we won't find.
EXPECT_EQ(midi_port_state_0_.end(),
midi_port_state_0_.FindDisconnected(*port_input_minimal_));
}
// Tests AlsaSeqState -> MidiPortState.
TEST_F(MidiManagerAlsaTest, ToMidiPortState) {
// Empty state.
EXPECT_EQ(0,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Still empty, because there are no ports yet.
alsa_seq_state_0_.ClientStart(0, "0", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(0,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add a port, now it has 1 item when converted.
alsa_seq_state_0_.PortStart(
0, 0, "0:0", MidiManagerAlsa::AlsaSeqState::PortDirection::kInput, true);
EXPECT_EQ(1,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Close client. This closes its ports and returns count to 0.
alsa_seq_state_0_.ClientExit(0);
EXPECT_EQ(0,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add another port, without client. This does nothing.
alsa_seq_state_0_.PortStart(
0, 0, "0:0", MidiManagerAlsa::AlsaSeqState::PortDirection::kInput, true);
EXPECT_EQ(0,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Close client again. This does nothing.
alsa_seq_state_0_.ClientExit(0);
EXPECT_EQ(0,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add duplex port. This will add 2 ports when converted.
alsa_seq_state_0_.ClientStart(0, "0", SND_SEQ_KERNEL_CLIENT);
alsa_seq_state_0_.PortStart(
0, 0, "0:0", MidiManagerAlsa::AlsaSeqState::PortDirection::kDuplex, true);
EXPECT_EQ(2,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add an output port. Now we are at 3.
alsa_seq_state_0_.PortStart(
0, 1, "0:1", MidiManagerAlsa::AlsaSeqState::PortDirection::kOutput, true);
EXPECT_EQ(3,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add another client. Still at 3.
alsa_seq_state_0_.ClientStart(1, "1", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(3,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add a port. Now at 4.
alsa_seq_state_0_.PortStart(
1, 0, "1:0", MidiManagerAlsa::AlsaSeqState::PortDirection::kInput, true);
EXPECT_EQ(4,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add a duplicate port. Still at 4.
alsa_seq_state_0_.PortStart(
1, 0, "1:0", MidiManagerAlsa::AlsaSeqState::PortDirection::kInput, true);
EXPECT_EQ(4,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Add a duplicate client. This will close the ports from the previous client.
alsa_seq_state_0_.ClientStart(1, "1", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(3,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Remove a duplex port. This reduces count by 2.
alsa_seq_state_0_.PortExit(0, 0);
EXPECT_EQ(1,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Remove a non-existent port. No change.
alsa_seq_state_0_.PortExit(0, 0);
EXPECT_EQ(1,
CountPorts(*alsa_seq_state_0_.ToMidiPortState(alsa_cards_).get()));
// Verify the last entry.
EXPECT_TRUE((*alsa_seq_state_0_.ToMidiPortState(alsa_cards_)->begin())
->MatchConnected(MidiManagerAlsa::MidiPort(
"", MidiManagerAlsa::MidiPort::Id(), 0, 1, -1, "0", "0:1",
"", "", MidiManagerAlsa::MidiPort::Type::kOutput)));
}
// Tests card_client_count of AlsaSeqState.
TEST_F(MidiManagerAlsaTest, CardClientCount) {
EXPECT_EQ(0, alsa_seq_state_0_.card_client_count());
// Add a kernel client.
alsa_seq_state_0_.ClientStart(16, "16", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
// Add a duplicate kernel client.
alsa_seq_state_0_.ClientStart(16, "16", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
// Add a duplicate user client.
alsa_seq_state_0_.ClientStart(16, "16", SND_SEQ_USER_CLIENT);
EXPECT_EQ(0, alsa_seq_state_0_.card_client_count());
// Add 2 more kernel clients.
alsa_seq_state_0_.ClientStart(17, "17", SND_SEQ_KERNEL_CLIENT);
alsa_seq_state_0_.ClientStart(18, "18", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(2, alsa_seq_state_0_.card_client_count());
// Add another user client.
alsa_seq_state_0_.ClientStart(101, "101", SND_SEQ_USER_CLIENT);
EXPECT_EQ(2, alsa_seq_state_0_.card_client_count());
// Remove kernel client.
alsa_seq_state_0_.ClientExit(17);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
// Remove user client.
alsa_seq_state_0_.ClientExit(16);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
// Remove kernel client.
alsa_seq_state_0_.ClientExit(18);
EXPECT_EQ(0, alsa_seq_state_0_.card_client_count());
// Add a duplicate kernel client.
alsa_seq_state_0_.ClientStart(101, "101", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
// Add a low kernel client.
alsa_seq_state_0_.ClientStart(1, "1", SND_SEQ_KERNEL_CLIENT);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
// Remove low kernel client.
alsa_seq_state_0_.ClientExit(1);
EXPECT_EQ(1, alsa_seq_state_0_.card_client_count());
}
TEST_F(MidiManagerAlsaTest, AlsaCards) {
// TODO(agoode): test add/remove of alsa cards.
}
// TODO(agoode): Test old -> new state event generation, using mocks.
} // namespace midi