1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/midi/midi_manager_usb.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/time/time.h"
11 #include "media/midi/usb_midi_device.h"
12 #include "testing/gtest/include/gtest/gtest.h"
18 template<typename T
, size_t N
>
19 std::vector
<T
> ToVector(const T (&array
)[N
]) {
20 return std::vector
<T
>(array
, array
+ N
);
28 void AddLog(const std::string
& message
) { log_
+= message
; }
29 std::string
TakeLog() {
38 DISALLOW_COPY_AND_ASSIGN(Logger
);
41 class FakeUsbMidiDevice
: public UsbMidiDevice
{
43 explicit FakeUsbMidiDevice(Logger
* logger
) : logger_(logger
) {}
44 virtual ~FakeUsbMidiDevice() {}
46 virtual std::vector
<uint8
> GetDescriptor() OVERRIDE
{
47 logger_
->AddLog("UsbMidiDevice::GetDescriptor\n");
51 virtual void Send(int endpoint_number
,
52 const std::vector
<uint8
>& data
) OVERRIDE
{
53 logger_
->AddLog("UsbMidiDevice::Send ");
54 logger_
->AddLog(base::StringPrintf("endpoint = %d data =",
56 for (size_t i
= 0; i
< data
.size(); ++i
)
57 logger_
->AddLog(base::StringPrintf(" 0x%02x", data
[i
]));
58 logger_
->AddLog("\n");
61 void SetDescriptor(const std::vector
<uint8
> descriptor
) {
62 descriptor_
= descriptor
;
66 std::vector
<uint8
> descriptor_
;
69 DISALLOW_COPY_AND_ASSIGN(FakeUsbMidiDevice
);
72 class FakeMidiManagerClient
: public MidiManagerClient
{
74 explicit FakeMidiManagerClient(Logger
* logger
)
75 : complete_start_session_(false),
76 result_(MIDI_NOT_SUPPORTED
),
78 virtual ~FakeMidiManagerClient() {}
80 virtual void CompleteStartSession(int client_id
, MidiResult result
) OVERRIDE
{
81 complete_start_session_
= true;
85 virtual void ReceiveMidiData(uint32 port_index
,
88 double timestamp
) OVERRIDE
{
89 logger_
->AddLog("MidiManagerClient::ReceiveMidiData ");
90 logger_
->AddLog(base::StringPrintf("port_index = %d data =", port_index
));
91 for (size_t i
= 0; i
< size
; ++i
)
92 logger_
->AddLog(base::StringPrintf(" 0x%02x", data
[i
]));
93 logger_
->AddLog("\n");
96 virtual void AccumulateMidiBytesSent(size_t size
) OVERRIDE
{
97 logger_
->AddLog("MidiManagerClient::AccumulateMidiBytesSent ");
98 // Windows has no "%zu".
99 logger_
->AddLog(base::StringPrintf("size = %u\n",
100 static_cast<unsigned>(size
)));
103 bool complete_start_session_
;
109 DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient
);
112 class TestUsbMidiDeviceFactory
: public UsbMidiDevice::Factory
{
114 TestUsbMidiDeviceFactory() {}
115 virtual ~TestUsbMidiDeviceFactory() {}
116 virtual void EnumerateDevices(UsbMidiDeviceDelegate
* device
,
117 Callback callback
) OVERRIDE
{
118 callback_
= callback
;
124 DISALLOW_COPY_AND_ASSIGN(TestUsbMidiDeviceFactory
);
127 class MidiManagerUsbForTesting
: public MidiManagerUsb
{
129 explicit MidiManagerUsbForTesting(
130 scoped_ptr
<UsbMidiDevice::Factory
> device_factory
)
131 : MidiManagerUsb(device_factory
.PassAs
<UsbMidiDevice::Factory
>()) {}
132 virtual ~MidiManagerUsbForTesting() {}
134 void CallCompleteInitialization(MidiResult result
) {
135 CompleteInitialization(result
);
139 DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbForTesting
);
142 class MidiManagerUsbTest
: public ::testing::Test
{
144 MidiManagerUsbTest() {
145 scoped_ptr
<TestUsbMidiDeviceFactory
> factory(new TestUsbMidiDeviceFactory
);
146 factory_
= factory
.get();
148 new MidiManagerUsbForTesting(factory
.PassAs
<UsbMidiDevice::Factory
>()));
150 virtual ~MidiManagerUsbTest() {
151 std::string leftover_logs
= logger_
.TakeLog();
152 if (!leftover_logs
.empty()) {
153 ADD_FAILURE() << "Log should be empty: " << leftover_logs
;
159 client_
.reset(new FakeMidiManagerClient(&logger_
));
160 manager_
->StartSession(client_
.get(), 0);
164 manager_
->EndSession(client_
.get());
167 bool IsInitializationCallbackInvoked() {
168 return client_
->complete_start_session_
;
171 MidiResult
GetInitializationResult() {
172 return client_
->result_
;
175 scoped_ptr
<MidiManagerUsbForTesting
> manager_
;
176 scoped_ptr
<FakeMidiManagerClient
> client_
;
177 // Owned by manager_.
178 TestUsbMidiDeviceFactory
* factory_
;
182 DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbTest
);
186 TEST_F(MidiManagerUsbTest
, Initialize
) {
187 scoped_ptr
<FakeUsbMidiDevice
> device(new FakeUsbMidiDevice(&logger_
));
188 uint8 descriptor
[] = {
189 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a,
190 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02,
191 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00,
192 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00,
193 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02,
194 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51,
195 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02,
196 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09,
197 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24,
198 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03,
199 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02,
200 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02,
201 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
202 0x05, 0x25, 0x01, 0x01, 0x07,
204 device
->SetDescriptor(ToVector(descriptor
));
207 ScopedVector
<UsbMidiDevice
> devices
;
208 devices
.push_back(device
.release());
209 EXPECT_FALSE(IsInitializationCallbackInvoked());
210 factory_
->callback_
.Run(true, &devices
);
211 EXPECT_TRUE(IsInitializationCallbackInvoked());
212 EXPECT_EQ(MIDI_OK
, GetInitializationResult());
214 ASSERT_EQ(1u, manager_
->input_ports().size());
215 ASSERT_EQ(2u, manager_
->output_ports().size());
216 ASSERT_TRUE(manager_
->input_stream());
217 std::vector
<UsbMidiInputStream::JackUniqueKey
> keys
=
218 manager_
->input_stream()->RegisteredJackKeysForTesting();
219 ASSERT_EQ(2u, manager_
->output_streams().size());
220 EXPECT_EQ(2u, manager_
->output_streams()[0]->jack().jack_id
);
221 EXPECT_EQ(3u, manager_
->output_streams()[1]->jack().jack_id
);
222 ASSERT_EQ(1u, keys
.size());
223 EXPECT_EQ(2, keys
[0].endpoint_number
);
225 EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_
.TakeLog());
228 TEST_F(MidiManagerUsbTest
, InitializeFail
) {
231 EXPECT_FALSE(IsInitializationCallbackInvoked());
232 factory_
->callback_
.Run(false, NULL
);
233 EXPECT_TRUE(IsInitializationCallbackInvoked());
234 EXPECT_EQ(MIDI_INITIALIZATION_ERROR
, GetInitializationResult());
237 TEST_F(MidiManagerUsbTest
, InitializeFailBecauseOfInvalidDescriptor
) {
238 scoped_ptr
<FakeUsbMidiDevice
> device(new FakeUsbMidiDevice(&logger_
));
239 uint8 descriptor
[] = {0x04};
240 device
->SetDescriptor(ToVector(descriptor
));
243 ScopedVector
<UsbMidiDevice
> devices
;
244 devices
.push_back(device
.release());
245 EXPECT_FALSE(IsInitializationCallbackInvoked());
246 factory_
->callback_
.Run(true, &devices
);
247 EXPECT_TRUE(IsInitializationCallbackInvoked());
248 EXPECT_EQ(MIDI_INITIALIZATION_ERROR
, GetInitializationResult());
249 EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_
.TakeLog());
252 TEST_F(MidiManagerUsbTest
, Send
) {
253 scoped_ptr
<FakeUsbMidiDevice
> device(new FakeUsbMidiDevice(&logger_
));
254 FakeMidiManagerClient
client(&logger_
);
255 uint8 descriptor
[] = {
256 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a,
257 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02,
258 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00,
259 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00,
260 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02,
261 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51,
262 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02,
263 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09,
264 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24,
265 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03,
266 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02,
267 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02,
268 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
269 0x05, 0x25, 0x01, 0x01, 0x07,
272 device
->SetDescriptor(ToVector(descriptor
));
275 0xf0, 0x00, 0x01, 0xf7,
279 ScopedVector
<UsbMidiDevice
> devices
;
280 devices
.push_back(device
.release());
281 EXPECT_FALSE(IsInitializationCallbackInvoked());
282 factory_
->callback_
.Run(true, &devices
);
283 EXPECT_TRUE(IsInitializationCallbackInvoked());
284 EXPECT_EQ(MIDI_OK
, GetInitializationResult());
285 ASSERT_EQ(2u, manager_
->output_streams().size());
287 manager_
->DispatchSendMidiData(&client
, 1, ToVector(data
), 0);
288 EXPECT_EQ("UsbMidiDevice::GetDescriptor\n"
289 "UsbMidiDevice::Send endpoint = 2 data = "
290 "0x19 0x90 0x45 0x7f "
291 "0x14 0xf0 0x00 0x01 "
292 "0x15 0xf7 0x00 0x00\n"
293 "MidiManagerClient::AccumulateMidiBytesSent size = 7\n",
297 TEST_F(MidiManagerUsbTest
, Receive
) {
298 scoped_ptr
<FakeUsbMidiDevice
> device(new FakeUsbMidiDevice(&logger_
));
299 uint8 descriptor
[] = {
300 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a,
301 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02,
302 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00,
303 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00,
304 0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02,
305 0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51,
306 0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02,
307 0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09,
308 0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24,
309 0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03,
310 0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02,
311 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02,
312 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
313 0x05, 0x25, 0x01, 0x01, 0x07,
316 device
->SetDescriptor(ToVector(descriptor
));
318 0x09, 0x90, 0x45, 0x7f,
319 0x04, 0xf0, 0x00, 0x01,
320 0x49, 0x90, 0x88, 0x99, // This data should be ignored (CN = 4).
321 0x05, 0xf7, 0x00, 0x00,
325 ScopedVector
<UsbMidiDevice
> devices
;
326 UsbMidiDevice
* device_raw
= device
.get();
327 devices
.push_back(device
.release());
328 EXPECT_FALSE(IsInitializationCallbackInvoked());
329 factory_
->callback_
.Run(true, &devices
);
330 EXPECT_TRUE(IsInitializationCallbackInvoked());
331 EXPECT_EQ(MIDI_OK
, GetInitializationResult());
333 manager_
->ReceiveUsbMidiData(device_raw
, 2, data
, arraysize(data
),
337 EXPECT_EQ("UsbMidiDevice::GetDescriptor\n"
338 "MidiManagerClient::ReceiveMidiData port_index = 0 "
339 "data = 0x90 0x45 0x7f\n"
340 "MidiManagerClient::ReceiveMidiData port_index = 0 "
341 "data = 0xf0 0x00 0x01\n"
342 "MidiManagerClient::ReceiveMidiData port_index = 0 data = 0xf7\n",