// Copyright 2014 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_usb.h" #include #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "media/midi/usb_midi_device.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { namespace midi { namespace { template std::vector ToVector(const T (&array)[N]) { return std::vector(array, array + N); } class Logger { public: Logger() {} ~Logger() {} void AddLog(const std::string& message) { log_ += message; } std::string TakeLog() { std::string result; result.swap(log_); return result; } private: std::string log_; DISALLOW_COPY_AND_ASSIGN(Logger); }; class FakeUsbMidiDevice : public UsbMidiDevice { public: explicit FakeUsbMidiDevice(Logger* logger) : logger_(logger) {} ~FakeUsbMidiDevice() override {} std::vector GetDescriptors() override { logger_->AddLog("UsbMidiDevice::GetDescriptors\n"); return descriptors_; } std::string GetManufacturer() override { return manufacturer_; } std::string GetProductName() override { return product_name_; } std::string GetDeviceVersion() override { return device_version_; } void Send(int endpoint_number, const std::vector& data) override { logger_->AddLog("UsbMidiDevice::Send "); logger_->AddLog(base::StringPrintf("endpoint = %d data =", endpoint_number)); for (size_t i = 0; i < data.size(); ++i) logger_->AddLog(base::StringPrintf(" 0x%02x", data[i])); logger_->AddLog("\n"); } void SetDescriptors(const std::vector descriptors) { descriptors_ = descriptors; } void SetManufacturer(const std::string& manufacturer) { manufacturer_ = manufacturer; } void SetProductName(const std::string& product_name) { product_name_ = product_name; } void SetDeviceVersion(const std::string& device_version) { device_version_ = device_version; } private: std::vector descriptors_; std::string manufacturer_; std::string product_name_; std::string device_version_; Logger* logger_; DISALLOW_COPY_AND_ASSIGN(FakeUsbMidiDevice); }; class FakeMidiManagerClient : public MidiManagerClient { public: explicit FakeMidiManagerClient(Logger* logger) : complete_start_session_(false), result_(Result::NOT_SUPPORTED), logger_(logger) {} ~FakeMidiManagerClient() override {} void AddInputPort(const MidiPortInfo& info) override { input_ports_.push_back(info); } void AddOutputPort(const MidiPortInfo& info) override { output_ports_.push_back(info); } void SetInputPortState(uint32 port_index, MidiPortState state) override {} void SetOutputPortState(uint32 port_index, MidiPortState state) override {} void CompleteStartSession(Result result) override { complete_start_session_ = true; result_ = result; } void ReceiveMidiData(uint32 port_index, const uint8* data, size_t size, double timestamp) override { logger_->AddLog("MidiManagerClient::ReceiveMidiData "); logger_->AddLog(base::StringPrintf("port_index = %d data =", port_index)); for (size_t i = 0; i < size; ++i) logger_->AddLog(base::StringPrintf(" 0x%02x", data[i])); logger_->AddLog("\n"); } void AccumulateMidiBytesSent(size_t size) override { logger_->AddLog("MidiManagerClient::AccumulateMidiBytesSent "); // Windows has no "%zu". logger_->AddLog(base::StringPrintf("size = %u\n", static_cast(size))); } bool complete_start_session_; Result result_; MidiPortInfoList input_ports_; MidiPortInfoList output_ports_; private: Logger* logger_; DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient); }; class TestUsbMidiDeviceFactory : public UsbMidiDevice::Factory { public: TestUsbMidiDeviceFactory() {} ~TestUsbMidiDeviceFactory() override {} void EnumerateDevices(UsbMidiDeviceDelegate* device, Callback callback) override { callback_ = callback; } Callback callback_; private: DISALLOW_COPY_AND_ASSIGN(TestUsbMidiDeviceFactory); }; class MidiManagerUsbForTesting : public MidiManagerUsb { public: explicit MidiManagerUsbForTesting( scoped_ptr device_factory) : MidiManagerUsb(device_factory.Pass()) {} ~MidiManagerUsbForTesting() override {} void CallCompleteInitialization(Result result) { CompleteInitialization(result); base::RunLoop run_loop; run_loop.RunUntilIdle(); } private: DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbForTesting); }; class MidiManagerUsbTest : public ::testing::Test { public: MidiManagerUsbTest() : message_loop_(new base::MessageLoop) { scoped_ptr factory(new TestUsbMidiDeviceFactory); factory_ = factory.get(); manager_.reset(new MidiManagerUsbForTesting(factory.Pass())); } ~MidiManagerUsbTest() override { std::string leftover_logs = logger_.TakeLog(); if (!leftover_logs.empty()) { ADD_FAILURE() << "Log should be empty: " << leftover_logs; } } protected: void Initialize() { client_.reset(new FakeMidiManagerClient(&logger_)); manager_->StartSession(client_.get()); } void Finalize() { manager_->EndSession(client_.get()); } bool IsInitializationCallbackInvoked() { return client_->complete_start_session_; } Result GetInitializationResult() { return client_->result_; } void RunCallbackUntilCallbackInvoked( bool result, UsbMidiDevice::Devices* devices) { factory_->callback_.Run(result, devices); while (!client_->complete_start_session_) { base::RunLoop run_loop; run_loop.RunUntilIdle(); } } const MidiPortInfoList& input_ports() { return client_->input_ports_; } const MidiPortInfoList& output_ports() { return client_->output_ports_; } scoped_ptr manager_; scoped_ptr client_; // Owned by manager_. TestUsbMidiDeviceFactory* factory_; Logger logger_; private: scoped_ptr message_loop_; DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbTest); }; TEST_F(MidiManagerUsbTest, Initialize) { scoped_ptr device(new FakeUsbMidiDevice(&logger_)); uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51, 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02, 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09, 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02, 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; device->SetDescriptors(ToVector(descriptors)); device->SetManufacturer("vendor1"); device->SetProductName("device1"); device->SetDeviceVersion("1.02"); Initialize(); ScopedVector devices; devices.push_back(device.Pass()); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::OK, GetInitializationResult()); ASSERT_EQ(1u, input_ports().size()); EXPECT_EQ("port-0-2", input_ports()[0].id); EXPECT_EQ("vendor1", input_ports()[0].manufacturer); EXPECT_EQ("device1", input_ports()[0].name); EXPECT_EQ("1.02", input_ports()[0].version); ASSERT_EQ(2u, output_ports().size()); EXPECT_EQ("port-0-0", output_ports()[0].id); EXPECT_EQ("vendor1", output_ports()[0].manufacturer); EXPECT_EQ("device1", output_ports()[0].name); EXPECT_EQ("1.02", output_ports()[0].version); EXPECT_EQ("port-0-1", output_ports()[1].id); EXPECT_EQ("vendor1", output_ports()[1].manufacturer); EXPECT_EQ("device1", output_ports()[1].name); EXPECT_EQ("1.02", output_ports()[1].version); ASSERT_TRUE(manager_->input_stream()); std::vector jacks = manager_->input_stream()->jacks(); ASSERT_EQ(2u, manager_->output_streams().size()); EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id); EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); ASSERT_EQ(1u, jacks.size()); EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, InitializeMultipleDevices) { scoped_ptr device1(new FakeUsbMidiDevice(&logger_)); scoped_ptr device2(new FakeUsbMidiDevice(&logger_)); uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51, 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02, 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09, 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02, 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; device1->SetDescriptors(ToVector(descriptors)); device1->SetManufacturer("vendor1"); device1->SetProductName("device1"); device1->SetDeviceVersion("1.02"); device2->SetDescriptors(ToVector(descriptors)); device2->SetManufacturer("vendor2"); device2->SetProductName("device2"); device2->SetDeviceVersion("98.76"); Initialize(); ScopedVector devices; devices.push_back(device1.Pass()); devices.push_back(device2.Pass()); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::OK, GetInitializationResult()); ASSERT_EQ(2u, input_ports().size()); EXPECT_EQ("port-0-2", input_ports()[0].id); EXPECT_EQ("vendor1", input_ports()[0].manufacturer); EXPECT_EQ("device1", input_ports()[0].name); EXPECT_EQ("1.02", input_ports()[0].version); EXPECT_EQ("port-1-2", input_ports()[1].id); EXPECT_EQ("vendor2", input_ports()[1].manufacturer); EXPECT_EQ("device2", input_ports()[1].name); EXPECT_EQ("98.76", input_ports()[1].version); ASSERT_EQ(4u, output_ports().size()); EXPECT_EQ("port-0-0", output_ports()[0].id); EXPECT_EQ("vendor1", output_ports()[0].manufacturer); EXPECT_EQ("device1", output_ports()[0].name); EXPECT_EQ("1.02", output_ports()[0].version); EXPECT_EQ("port-0-1", output_ports()[1].id); EXPECT_EQ("vendor1", output_ports()[1].manufacturer); EXPECT_EQ("device1", output_ports()[1].name); EXPECT_EQ("1.02", output_ports()[1].version); EXPECT_EQ("port-1-0", output_ports()[2].id); EXPECT_EQ("vendor2", output_ports()[2].manufacturer); EXPECT_EQ("device2", output_ports()[2].name); EXPECT_EQ("98.76", output_ports()[2].version); EXPECT_EQ("port-1-1", output_ports()[3].id); EXPECT_EQ("vendor2", output_ports()[3].manufacturer); EXPECT_EQ("device2", output_ports()[3].name); EXPECT_EQ("98.76", output_ports()[3].version); ASSERT_TRUE(manager_->input_stream()); std::vector jacks = manager_->input_stream()->jacks(); ASSERT_EQ(4u, manager_->output_streams().size()); EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id); EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); ASSERT_EQ(2u, jacks.size()); EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ( "UsbMidiDevice::GetDescriptors\n" "UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, InitializeFail) { Initialize(); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(false, NULL); EXPECT_EQ(Result::INITIALIZATION_ERROR, GetInitializationResult()); } TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptors) { scoped_ptr device(new FakeUsbMidiDevice(&logger_)); uint8 descriptors[] = {0x04}; device->SetDescriptors(ToVector(descriptors)); Initialize(); ScopedVector devices; devices.push_back(device.Pass()); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::INITIALIZATION_ERROR, GetInitializationResult()); EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, Send) { Initialize(); scoped_ptr device(new FakeUsbMidiDevice(&logger_)); uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51, 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02, 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09, 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02, 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; device->SetDescriptors(ToVector(descriptors)); uint8 data[] = { 0x90, 0x45, 0x7f, 0xf0, 0x00, 0x01, 0xf7, }; ScopedVector devices; devices.push_back(device.Pass()); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::OK, GetInitializationResult()); ASSERT_EQ(2u, manager_->output_streams().size()); manager_->DispatchSendMidiData(client_.get(), 1, ToVector(data), 0); // Since UsbMidiDevice::Send is posted as a task, RunLoop should run to // invoke the task. base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_EQ("UsbMidiDevice::GetDescriptors\n" "UsbMidiDevice::Send endpoint = 2 data = " "0x19 0x90 0x45 0x7f " "0x14 0xf0 0x00 0x01 " "0x15 0xf7 0x00 0x00\n" "MidiManagerClient::AccumulateMidiBytesSent size = 7\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, SendFromCompromizedRenderer) { scoped_ptr device(new FakeUsbMidiDevice(&logger_)); uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51, 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02, 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09, 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02, 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; device->SetDescriptors(ToVector(descriptors)); uint8 data[] = { 0x90, 0x45, 0x7f, 0xf0, 0x00, 0x01, 0xf7, }; Initialize(); ScopedVector devices; devices.push_back(device.Pass()); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::OK, GetInitializationResult()); ASSERT_EQ(2u, manager_->output_streams().size()); EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); // The specified port index is invalid. The manager must ignore the request. manager_->DispatchSendMidiData(client_.get(), 99, ToVector(data), 0); EXPECT_EQ("", logger_.TakeLog()); // The specified port index is invalid. The manager must ignore the request. manager_->DispatchSendMidiData(client_.get(), 2, ToVector(data), 0); EXPECT_EQ("", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, Receive) { scoped_ptr device(new FakeUsbMidiDevice(&logger_)); uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51, 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02, 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09, 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02, 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; device->SetDescriptors(ToVector(descriptors)); uint8 data[] = { 0x09, 0x90, 0x45, 0x7f, 0x04, 0xf0, 0x00, 0x01, 0x49, 0x90, 0x88, 0x99, // This data should be ignored (CN = 4). 0x05, 0xf7, 0x00, 0x00, }; Initialize(); ScopedVector devices; UsbMidiDevice* device_raw = device.get(); devices.push_back(device.Pass()); EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::OK, GetInitializationResult()); manager_->ReceiveUsbMidiData(device_raw, 2, data, arraysize(data), base::TimeTicks()); Finalize(); EXPECT_EQ("UsbMidiDevice::GetDescriptors\n" "MidiManagerClient::ReceiveMidiData port_index = 0 " "data = 0x90 0x45 0x7f\n" "MidiManagerClient::ReceiveMidiData port_index = 0 " "data = 0xf0 0x00 0x01\n" "MidiManagerClient::ReceiveMidiData port_index = 0 data = 0xf7\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, AttachDevice) { uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51, 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02, 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09, 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03, 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02, 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; Initialize(); ScopedVector devices; EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(Result::OK, GetInitializationResult()); ASSERT_EQ(0u, input_ports().size()); ASSERT_EQ(0u, output_ports().size()); ASSERT_TRUE(manager_->input_stream()); std::vector jacks = manager_->input_stream()->jacks(); ASSERT_EQ(0u, manager_->output_streams().size()); ASSERT_EQ(0u, jacks.size()); EXPECT_EQ("", logger_.TakeLog()); scoped_ptr new_device(new FakeUsbMidiDevice(&logger_)); new_device->SetDescriptors(ToVector(descriptors)); manager_->OnDeviceAttached(new_device.Pass()); ASSERT_EQ(1u, input_ports().size()); ASSERT_EQ(2u, output_ports().size()); ASSERT_TRUE(manager_->input_stream()); jacks = manager_->input_stream()->jacks(); ASSERT_EQ(2u, manager_->output_streams().size()); EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id); EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); ASSERT_EQ(1u, jacks.size()); EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } } // namespace } // namespace midi } // namespace media