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/usb_midi_input_stream.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/time/time.h"
17 #include "media/midi/usb_midi_device.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 using base::TimeTicks;
21 
22 namespace midi {
23 
24 namespace {
25 
26 class TestUsbMidiDevice : public UsbMidiDevice {
27  public:
28   TestUsbMidiDevice() = default;
29   ~TestUsbMidiDevice() override = default;
GetDescriptors()30   std::vector<uint8_t> GetDescriptors() override {
31     return std::vector<uint8_t>();
32   }
GetManufacturer()33   std::string GetManufacturer() override { return std::string(); }
GetProductName()34   std::string GetProductName() override { return std::string(); }
GetDeviceVersion()35   std::string GetDeviceVersion() override { return std::string(); }
Send(int endpoint_number,const std::vector<uint8_t> & data)36   void Send(int endpoint_number, const std::vector<uint8_t>& data) override {}
37 
38  private:
39   DISALLOW_COPY_AND_ASSIGN(TestUsbMidiDevice);
40 };
41 
42 class MockDelegate : public UsbMidiInputStream::Delegate {
43  public:
44   MockDelegate() = default;
45   ~MockDelegate() override = default;
OnReceivedData(size_t jack_index,const uint8_t * data,size_t size,base::TimeTicks time)46   void OnReceivedData(size_t jack_index,
47                       const uint8_t* data,
48                       size_t size,
49                       base::TimeTicks time) override {
50     for (size_t i = 0; i < size; ++i)
51       received_data_ += base::StringPrintf("0x%02x ", data[i]);
52     received_data_ += "\n";
53   }
54 
received_data() const55   const std::string& received_data() const { return received_data_; }
56 
57  private:
58   std::string received_data_;
59   DISALLOW_COPY_AND_ASSIGN(MockDelegate);
60 };
61 
62 class UsbMidiInputStreamTest : public ::testing::Test {
63  protected:
UsbMidiInputStreamTest()64   UsbMidiInputStreamTest() {
65     stream_.reset(new UsbMidiInputStream(&delegate_));
66 
67     stream_->Add(UsbMidiJack(&device1_,
68                              84,  // jack_id
69                              4,  // cable_number
70                              135));  // endpoint_address
71     stream_->Add(UsbMidiJack(&device2_,
72                              85,
73                              5,
74                              137));
75     stream_->Add(UsbMidiJack(&device2_,
76                              84,
77                              4,
78                              135));
79     stream_->Add(UsbMidiJack(&device1_,
80                              85,
81                              5,
82                              135));
83   }
84 
85   TestUsbMidiDevice device1_;
86   TestUsbMidiDevice device2_;
87   MockDelegate delegate_;
88   std::unique_ptr<UsbMidiInputStream> stream_;
89 
90  private:
91   DISALLOW_COPY_AND_ASSIGN(UsbMidiInputStreamTest);
92 };
93 
TEST_F(UsbMidiInputStreamTest,UnknownMessage)94 TEST_F(UsbMidiInputStreamTest, UnknownMessage) {
95   uint8_t data[] = {
96       0x40, 0xff, 0xff, 0xff, 0x41, 0xff, 0xff, 0xff,
97   };
98 
99   stream_->OnReceivedData(&device1_, 7, data, base::size(data), TimeTicks());
100   EXPECT_EQ("", delegate_.received_data());
101 }
102 
TEST_F(UsbMidiInputStreamTest,SystemCommonMessage)103 TEST_F(UsbMidiInputStreamTest, SystemCommonMessage) {
104   uint8_t data[] = {
105       0x45, 0xf8, 0x00, 0x00, 0x42, 0xf3, 0x22, 0x00, 0x43, 0xf2, 0x33, 0x44,
106   };
107 
108   stream_->OnReceivedData(&device1_, 7, data, base::size(data), TimeTicks());
109   EXPECT_EQ("0xf8 \n"
110             "0xf3 0x22 \n"
111             "0xf2 0x33 0x44 \n", delegate_.received_data());
112 }
113 
TEST_F(UsbMidiInputStreamTest,SystemExclusiveMessage)114 TEST_F(UsbMidiInputStreamTest, SystemExclusiveMessage) {
115   uint8_t data[] = {
116       0x44, 0xf0, 0x11, 0x22, 0x45, 0xf7, 0x00, 0x00,
117       0x46, 0xf0, 0xf7, 0x00, 0x47, 0xf0, 0x33, 0xf7,
118   };
119 
120   stream_->OnReceivedData(&device1_, 7, data, base::size(data), TimeTicks());
121   EXPECT_EQ("0xf0 0x11 0x22 \n"
122             "0xf7 \n"
123             "0xf0 0xf7 \n"
124             "0xf0 0x33 0xf7 \n", delegate_.received_data());
125 }
126 
TEST_F(UsbMidiInputStreamTest,ChannelMessage)127 TEST_F(UsbMidiInputStreamTest, ChannelMessage) {
128   uint8_t data[] = {
129       0x48, 0x80, 0x11, 0x22, 0x49, 0x90, 0x33, 0x44, 0x4a, 0xa0,
130       0x55, 0x66, 0x4b, 0xb0, 0x77, 0x88, 0x4c, 0xc0, 0x99, 0x00,
131       0x4d, 0xd0, 0xaa, 0x00, 0x4e, 0xe0, 0xbb, 0xcc,
132   };
133 
134   stream_->OnReceivedData(&device1_, 7, data, base::size(data), TimeTicks());
135   EXPECT_EQ("0x80 0x11 0x22 \n"
136             "0x90 0x33 0x44 \n"
137             "0xa0 0x55 0x66 \n"
138             "0xb0 0x77 0x88 \n"
139             "0xc0 0x99 \n"
140             "0xd0 0xaa \n"
141             "0xe0 0xbb 0xcc \n", delegate_.received_data());
142 }
143 
TEST_F(UsbMidiInputStreamTest,SingleByteMessage)144 TEST_F(UsbMidiInputStreamTest, SingleByteMessage) {
145   uint8_t data[] = {
146       0x4f, 0xf8, 0x00, 0x00,
147   };
148 
149   stream_->OnReceivedData(&device1_, 7, data, base::size(data), TimeTicks());
150   EXPECT_EQ("0xf8 \n", delegate_.received_data());
151 }
152 
TEST_F(UsbMidiInputStreamTest,DispatchForMultipleCables)153 TEST_F(UsbMidiInputStreamTest, DispatchForMultipleCables) {
154   uint8_t data[] = {
155       0x4f, 0xf8, 0x00, 0x00, 0x5f, 0xfa, 0x00, 0x00, 0x6f, 0xfb, 0x00, 0x00,
156   };
157 
158   stream_->OnReceivedData(&device1_, 7, data, base::size(data), TimeTicks());
159   EXPECT_EQ("0xf8 \n0xfa \n", delegate_.received_data());
160 }
161 
TEST_F(UsbMidiInputStreamTest,DispatchForDevice2)162 TEST_F(UsbMidiInputStreamTest, DispatchForDevice2) {
163   uint8_t data[] = {0x4f, 0xf8, 0x00, 0x00};
164 
165   stream_->OnReceivedData(&device2_, 7, data, base::size(data), TimeTicks());
166   EXPECT_EQ("0xf8 \n", delegate_.received_data());
167 }
168 
169 }  // namespace
170 
171 }  // namespace midi
172