Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / midi / midi_manager_usb_unittest.cc
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.
4
5 #include "media/midi/midi_manager_usb.h"
6
7 #include <string>
8
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h"
13 #include "media/midi/usb_midi_device.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace media {
17
18 namespace {
19
20 template<typename T, size_t N>
21 std::vector<T> ToVector(const T (&array)[N]) {
22   return std::vector<T>(array, array + N);
23 }
24
25 class Logger {
26  public:
27   Logger() {}
28   ~Logger() {}
29
30   void AddLog(const std::string& message) { log_ += message; }
31   std::string TakeLog() {
32     std::string result;
33     result.swap(log_);
34     return result;
35   }
36
37  private:
38   std::string log_;
39
40   DISALLOW_COPY_AND_ASSIGN(Logger);
41 };
42
43 class FakeUsbMidiDevice : public UsbMidiDevice {
44  public:
45   explicit FakeUsbMidiDevice(Logger* logger) : logger_(logger) {}
46   ~FakeUsbMidiDevice() override {}
47
48   std::vector<uint8> GetDescriptor() override {
49     logger_->AddLog("UsbMidiDevice::GetDescriptor\n");
50     return descriptor_;
51   }
52
53   void Send(int endpoint_number, const std::vector<uint8>& data) override {
54     logger_->AddLog("UsbMidiDevice::Send ");
55     logger_->AddLog(base::StringPrintf("endpoint = %d data =",
56                                        endpoint_number));
57     for (size_t i = 0; i < data.size(); ++i)
58       logger_->AddLog(base::StringPrintf(" 0x%02x", data[i]));
59     logger_->AddLog("\n");
60   }
61
62   void SetDescriptor(const std::vector<uint8> descriptor) {
63     descriptor_ = descriptor;
64   }
65
66  private:
67   std::vector<uint8> descriptor_;
68   Logger* logger_;
69
70   DISALLOW_COPY_AND_ASSIGN(FakeUsbMidiDevice);
71 };
72
73 class FakeMidiManagerClient : public MidiManagerClient {
74  public:
75   explicit FakeMidiManagerClient(Logger* logger)
76       : complete_start_session_(false),
77         result_(MIDI_NOT_SUPPORTED),
78         logger_(logger) {}
79   ~FakeMidiManagerClient() override {}
80
81   void AddInputPort(const MidiPortInfo& info) override {
82     input_ports_.push_back(info);
83   }
84
85   void AddOutputPort(const MidiPortInfo& info) override {
86     output_ports_.push_back(info);
87   }
88
89   void CompleteStartSession(MidiResult result) override {
90     complete_start_session_ = true;
91     result_ = result;
92   }
93
94   void ReceiveMidiData(uint32 port_index,
95                        const uint8* data,
96                        size_t size,
97                        double timestamp) override {
98     logger_->AddLog("MidiManagerClient::ReceiveMidiData ");
99     logger_->AddLog(base::StringPrintf("port_index = %d data =", port_index));
100     for (size_t i = 0; i < size; ++i)
101       logger_->AddLog(base::StringPrintf(" 0x%02x", data[i]));
102     logger_->AddLog("\n");
103   }
104
105   void AccumulateMidiBytesSent(size_t size) override {
106     logger_->AddLog("MidiManagerClient::AccumulateMidiBytesSent ");
107     // Windows has no "%zu".
108     logger_->AddLog(base::StringPrintf("size = %u\n",
109                                        static_cast<unsigned>(size)));
110   }
111
112   bool complete_start_session_;
113   MidiResult result_;
114   MidiPortInfoList input_ports_;
115   MidiPortInfoList output_ports_;
116
117  private:
118   Logger* logger_;
119
120   DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient);
121 };
122
123 class TestUsbMidiDeviceFactory : public UsbMidiDevice::Factory {
124  public:
125   TestUsbMidiDeviceFactory() {}
126   ~TestUsbMidiDeviceFactory() override {}
127   void EnumerateDevices(UsbMidiDeviceDelegate* device,
128                         Callback callback) override {
129     callback_ = callback;
130   }
131
132   Callback callback_;
133
134  private:
135   DISALLOW_COPY_AND_ASSIGN(TestUsbMidiDeviceFactory);
136 };
137
138 class MidiManagerUsbForTesting : public MidiManagerUsb {
139  public:
140   explicit MidiManagerUsbForTesting(
141       scoped_ptr<UsbMidiDevice::Factory> device_factory)
142       : MidiManagerUsb(device_factory.Pass()) {}
143   ~MidiManagerUsbForTesting() override {}
144
145   void CallCompleteInitialization(MidiResult result) {
146     CompleteInitialization(result);
147     base::RunLoop run_loop;
148     run_loop.RunUntilIdle();
149   }
150
151  private:
152   DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbForTesting);
153 };
154
155 class MidiManagerUsbTest : public ::testing::Test {
156  public:
157   MidiManagerUsbTest() : message_loop_(new base::MessageLoop) {
158     scoped_ptr<TestUsbMidiDeviceFactory> factory(new TestUsbMidiDeviceFactory);
159     factory_ = factory.get();
160     manager_.reset(new MidiManagerUsbForTesting(factory.Pass()));
161   }
162   ~MidiManagerUsbTest() override {
163     std::string leftover_logs = logger_.TakeLog();
164     if (!leftover_logs.empty()) {
165       ADD_FAILURE() << "Log should be empty: " << leftover_logs;
166     }
167   }
168
169  protected:
170   void Initialize() {
171     client_.reset(new FakeMidiManagerClient(&logger_));
172     manager_->StartSession(client_.get());
173   }
174
175   void Finalize() {
176     manager_->EndSession(client_.get());
177   }
178
179   bool IsInitializationCallbackInvoked() {
180     return client_->complete_start_session_;
181   }
182
183   MidiResult GetInitializationResult() {
184     return client_->result_;
185   }
186
187   void RunCallbackUntilCallbackInvoked(
188       bool result, UsbMidiDevice::Devices* devices) {
189     factory_->callback_.Run(result, devices);
190     while (!client_->complete_start_session_) {
191       base::RunLoop run_loop;
192       run_loop.RunUntilIdle();
193     }
194   }
195
196   const MidiPortInfoList& input_ports() { return client_->input_ports_; }
197   const MidiPortInfoList& output_ports() { return client_->output_ports_; }
198
199   scoped_ptr<MidiManagerUsbForTesting> manager_;
200   scoped_ptr<FakeMidiManagerClient> client_;
201   // Owned by manager_.
202   TestUsbMidiDeviceFactory* factory_;
203   Logger logger_;
204
205  private:
206   scoped_ptr<base::MessageLoop> message_loop_;
207
208   DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbTest);
209 };
210
211
212 TEST_F(MidiManagerUsbTest, Initialize) {
213   scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_));
214   uint8 descriptor[] = {
215     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a,
216     0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02,
217     0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00,
218     0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00,
219     0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02,
220     0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51,
221     0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02,
222     0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09,
223     0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24,
224     0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03,
225     0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02,
226     0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02,
227     0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
228     0x05, 0x25, 0x01, 0x01, 0x07,
229   };
230   device->SetDescriptor(ToVector(descriptor));
231
232   Initialize();
233   ScopedVector<UsbMidiDevice> devices;
234   devices.push_back(device.release());
235   EXPECT_FALSE(IsInitializationCallbackInvoked());
236   RunCallbackUntilCallbackInvoked(true, &devices);
237   EXPECT_EQ(MIDI_OK, GetInitializationResult());
238
239   ASSERT_EQ(1u, input_ports().size());
240   ASSERT_EQ(2u, output_ports().size());
241   ASSERT_TRUE(manager_->input_stream());
242   std::vector<UsbMidiInputStream::JackUniqueKey> keys =
243       manager_->input_stream()->RegisteredJackKeysForTesting();
244   ASSERT_EQ(2u, manager_->output_streams().size());
245   EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id);
246   EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id);
247   ASSERT_EQ(1u, keys.size());
248   EXPECT_EQ(2, keys[0].endpoint_number);
249
250   EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog());
251 }
252
253 TEST_F(MidiManagerUsbTest, InitializeFail) {
254   Initialize();
255
256   EXPECT_FALSE(IsInitializationCallbackInvoked());
257   RunCallbackUntilCallbackInvoked(false, NULL);
258   EXPECT_EQ(MIDI_INITIALIZATION_ERROR, GetInitializationResult());
259 }
260
261 TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptor) {
262   scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_));
263   uint8 descriptor[] = {0x04};
264   device->SetDescriptor(ToVector(descriptor));
265
266   Initialize();
267   ScopedVector<UsbMidiDevice> devices;
268   devices.push_back(device.release());
269   EXPECT_FALSE(IsInitializationCallbackInvoked());
270   RunCallbackUntilCallbackInvoked(true, &devices);
271   EXPECT_EQ(MIDI_INITIALIZATION_ERROR, GetInitializationResult());
272   EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog());
273 }
274
275 TEST_F(MidiManagerUsbTest, Send) {
276   scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_));
277   FakeMidiManagerClient client(&logger_);
278   uint8 descriptor[] = {
279     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a,
280     0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02,
281     0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00,
282     0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00,
283     0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02,
284     0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51,
285     0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02,
286     0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09,
287     0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24,
288     0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03,
289     0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02,
290     0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02,
291     0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
292     0x05, 0x25, 0x01, 0x01, 0x07,
293   };
294
295   device->SetDescriptor(ToVector(descriptor));
296   uint8 data[] = {
297     0x90, 0x45, 0x7f,
298     0xf0, 0x00, 0x01, 0xf7,
299   };
300
301   Initialize();
302   ScopedVector<UsbMidiDevice> devices;
303   devices.push_back(device.release());
304   EXPECT_FALSE(IsInitializationCallbackInvoked());
305   RunCallbackUntilCallbackInvoked(true, &devices);
306   EXPECT_EQ(MIDI_OK, GetInitializationResult());
307   ASSERT_EQ(2u, manager_->output_streams().size());
308
309   manager_->DispatchSendMidiData(&client, 1, ToVector(data), 0);
310   EXPECT_EQ("UsbMidiDevice::GetDescriptor\n"
311             "UsbMidiDevice::Send endpoint = 2 data = "
312             "0x19 0x90 0x45 0x7f "
313             "0x14 0xf0 0x00 0x01 "
314             "0x15 0xf7 0x00 0x00\n"
315             "MidiManagerClient::AccumulateMidiBytesSent size = 7\n",
316             logger_.TakeLog());
317 }
318
319 TEST_F(MidiManagerUsbTest, Receive) {
320   scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_));
321   uint8 descriptor[] = {
322     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a,
323     0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02,
324     0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00,
325     0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x09, 0x24, 0x01, 0x00,
326     0x01, 0x09, 0x00, 0x01, 0x01, 0x09, 0x04, 0x01, 0x00, 0x02,
327     0x01, 0x03, 0x00, 0x00, 0x07, 0x24, 0x01, 0x00, 0x01, 0x51,
328     0x00, 0x06, 0x24, 0x02, 0x01, 0x02, 0x00, 0x06, 0x24, 0x02,
329     0x01, 0x03, 0x00, 0x06, 0x24, 0x02, 0x02, 0x06, 0x00, 0x09,
330     0x24, 0x03, 0x01, 0x07, 0x01, 0x06, 0x01, 0x00, 0x09, 0x24,
331     0x03, 0x02, 0x04, 0x01, 0x02, 0x01, 0x00, 0x09, 0x24, 0x03,
332     0x02, 0x05, 0x01, 0x03, 0x01, 0x00, 0x09, 0x05, 0x02, 0x02,
333     0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x01, 0x02, 0x02,
334     0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
335     0x05, 0x25, 0x01, 0x01, 0x07,
336   };
337
338   device->SetDescriptor(ToVector(descriptor));
339   uint8 data[] = {
340     0x09, 0x90, 0x45, 0x7f,
341     0x04, 0xf0, 0x00, 0x01,
342     0x49, 0x90, 0x88, 0x99,  // This data should be ignored (CN = 4).
343     0x05, 0xf7, 0x00, 0x00,
344   };
345
346   Initialize();
347   ScopedVector<UsbMidiDevice> devices;
348   UsbMidiDevice* device_raw = device.get();
349   devices.push_back(device.release());
350   EXPECT_FALSE(IsInitializationCallbackInvoked());
351   RunCallbackUntilCallbackInvoked(true, &devices);
352   EXPECT_EQ(MIDI_OK, GetInitializationResult());
353
354   manager_->ReceiveUsbMidiData(device_raw, 2, data, arraysize(data),
355                                base::TimeTicks());
356   Finalize();
357
358   EXPECT_EQ("UsbMidiDevice::GetDescriptor\n"
359             "MidiManagerClient::ReceiveMidiData port_index = 0 "
360             "data = 0x90 0x45 0x7f\n"
361             "MidiManagerClient::ReceiveMidiData port_index = 0 "
362             "data = 0xf0 0x00 0x01\n"
363             "MidiManagerClient::ReceiveMidiData port_index = 0 data = 0xf7\n",
364             logger_.TakeLog());
365 }
366
367 }  // namespace
368
369 }  // namespace media