diff options
author | yhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-29 09:27:41 +0000 |
---|---|---|
committer | yhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-29 09:27:41 +0000 |
commit | a2a4a77c398d65391bd3f46ac90ce79718cf3823 (patch) | |
tree | d8bac8b65a9dd148b77ec1d35915c1c1af2d0cd4 /media/midi/midi_manager_usb_unittest.cc | |
parent | 976aa18fbf2a925265dac5ff524f9e33cd572973 (diff) | |
download | chromium_src-a2a4a77c398d65391bd3f46ac90ce79718cf3823.zip chromium_src-a2a4a77c398d65391bd3f46ac90ce79718cf3823.tar.gz chromium_src-a2a4a77c398d65391bd3f46ac90ce79718cf3823.tar.bz2 |
[WebMIDI] Introduce MidiManagerUsb
Introduce MidiManagerUsb, a MIDIManager subclass for USB-MIDI.
Android port will use this class.
BUG=303596
R=toyoshim@chromium.org
Review URL: https://codereview.chromium.org/107163008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247665 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/midi/midi_manager_usb_unittest.cc')
-rw-r--r-- | media/midi/midi_manager_usb_unittest.cc | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/media/midi/midi_manager_usb_unittest.cc b/media/midi/midi_manager_usb_unittest.cc new file mode 100644 index 0000000..1eb779d --- /dev/null +++ b/media/midi/midi_manager_usb_unittest.cc @@ -0,0 +1,318 @@ +// 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 <string> + +#include "base/strings/stringprintf.h" +#include "media/midi/usb_midi_device.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +namespace { + +template<typename T, size_t N> +std::vector<T> ToVector(const T (&array)[N]) { + return std::vector<T>(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) {} + virtual ~FakeUsbMidiDevice() {} + + virtual std::vector<uint8> GetDescriptor() OVERRIDE { + logger_->AddLog("UsbMidiDevice::GetDescriptor\n"); + return descriptor_; + } + + virtual void Send(int endpoint_number, + const std::vector<uint8>& 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 SetDescriptor(const std::vector<uint8> descriptor) { + descriptor_ = descriptor; + } + + private: + std::vector<uint8> descriptor_; + Logger* logger_; + + DISALLOW_COPY_AND_ASSIGN(FakeUsbMidiDevice); +}; + +class FakeMidiManagerClient : public MIDIManagerClient { + public: + explicit FakeMidiManagerClient(Logger* logger) : logger_(logger) {} + virtual ~FakeMidiManagerClient() {} + + virtual 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"); + } + + virtual void AccumulateMIDIBytesSent(size_t size) OVERRIDE { + logger_->AddLog("MIDIManagerClient::AccumulateMIDIBytesSent "); + // Windows has no "%zu". + logger_->AddLog(base::StringPrintf("size = %u\n", + static_cast<unsigned>(size))); + } + + private: + Logger* logger_; + + DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient); +}; + +class TestUsbMidiDeviceFactory : public UsbMidiDevice::Factory { + public: + TestUsbMidiDeviceFactory() {} + virtual ~TestUsbMidiDeviceFactory() {} + virtual void EnumerateDevices(UsbMidiDeviceDelegate* device, + Callback callback) OVERRIDE { + callback_ = callback; + } + + Callback callback_; + + private: + DISALLOW_COPY_AND_ASSIGN(TestUsbMidiDeviceFactory); +}; + +class MidiManagerUsbTest : public ::testing::Test { + public: + MidiManagerUsbTest() + : initialize_callback_run_(false), initialize_result_(false) { + scoped_ptr<TestUsbMidiDeviceFactory> factory(new TestUsbMidiDeviceFactory); + factory_ = factory.get(); + manager_.reset( + new MidiManagerUsb(factory.PassAs<UsbMidiDevice::Factory>())); + } + virtual ~MidiManagerUsbTest() { + std::string leftover_logs = logger_.TakeLog(); + if (!leftover_logs.empty()) { + ADD_FAILURE() << "Log should be empty: " << leftover_logs; + } + } + + protected: + void Initialize() { + manager_->Initialize(base::Bind(&MidiManagerUsbTest::OnInitializeDone, + base::Unretained(this))); + } + + void OnInitializeDone(bool result) { + initialize_callback_run_ = true; + initialize_result_ = result; + } + + bool initialize_callback_run_; + bool initialize_result_; + + scoped_ptr<MidiManagerUsb> manager_; + // Owned by manager_. + TestUsbMidiDeviceFactory* factory_; + Logger logger_; + + private: + DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbTest); +}; + + +TEST_F(MidiManagerUsbTest, Initialize) { + scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); + uint8 descriptor[] = { + 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->SetDescriptor(ToVector(descriptor)); + + Initialize(); + ScopedVector<UsbMidiDevice> devices; + devices.push_back(device.release()); + EXPECT_FALSE(initialize_callback_run_); + factory_->callback_.Run(true, &devices); + EXPECT_TRUE(initialize_callback_run_); + EXPECT_TRUE(initialize_result_); + + ASSERT_EQ(1u, manager_->input_ports().size()); + ASSERT_EQ(2u, manager_->output_ports().size()); + ASSERT_TRUE(manager_->input_stream()); + std::vector<UsbMidiInputStream::JackUniqueKey> keys = + manager_->input_stream()->RegisteredJackKeysForTesting(); + 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, keys.size()); + EXPECT_EQ(2, keys[0].endpoint_number); + + EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); +} + +TEST_F(MidiManagerUsbTest, InitializeFail) { + Initialize(); + + EXPECT_FALSE(initialize_callback_run_); + factory_->callback_.Run(false, NULL); + EXPECT_TRUE(initialize_callback_run_); + EXPECT_FALSE(initialize_result_); +} + +TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptor) { + scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); + uint8 descriptor[] = {0x04}; + device->SetDescriptor(ToVector(descriptor)); + + Initialize(); + ScopedVector<UsbMidiDevice> devices; + devices.push_back(device.release()); + EXPECT_FALSE(initialize_callback_run_); + factory_->callback_.Run(true, &devices); + EXPECT_TRUE(initialize_callback_run_); + EXPECT_FALSE(initialize_result_); + EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); +} + +TEST_F(MidiManagerUsbTest, Send) { + scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); + FakeMidiManagerClient client(&logger_); + uint8 descriptor[] = { + 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->SetDescriptor(ToVector(descriptor)); + uint8 data[] = { + 0x90, 0x45, 0x7f, + 0xf0, 0x00, 0x01, 0xf7, + }; + + Initialize(); + ScopedVector<UsbMidiDevice> devices; + devices.push_back(device.release()); + EXPECT_FALSE(initialize_callback_run_); + factory_->callback_.Run(true, &devices); + ASSERT_TRUE(initialize_callback_run_); + ASSERT_TRUE(initialize_result_); + ASSERT_EQ(2u, manager_->output_streams().size()); + + manager_->DispatchSendMIDIData(&client, 1, ToVector(data), 0); + EXPECT_EQ("UsbMidiDevice::GetDescriptor\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, Receive) { + scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); + FakeMidiManagerClient client(&logger_); + uint8 descriptor[] = { + 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->SetDescriptor(ToVector(descriptor)); + 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<UsbMidiDevice> devices; + UsbMidiDevice* device_raw = device.get(); + devices.push_back(device.release()); + EXPECT_FALSE(initialize_callback_run_); + factory_->callback_.Run(true, &devices); + ASSERT_TRUE(initialize_callback_run_); + ASSERT_TRUE(initialize_result_); + + manager_->StartSession(&client); + manager_->ReceiveUsbMidiData(device_raw, 2, data, arraysize(data), 0); + manager_->EndSession(&client); + + EXPECT_EQ("UsbMidiDevice::GetDescriptor\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()); +} + +} // namespace + +} // namespace media |