Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / media / midi_host_unittest.cc
blob877c80dee03c6f6a6d757b1b15264cbfd5c0ce91
1 // Copyright 2013 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 "content/browser/media/midi_host.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "content/common/media/midi_messages.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "media/midi/midi_manager.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace content {
16 namespace {
18 const uint8 kGMOn[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 };
19 const uint8 kGSOn[] = {
20 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7,
22 const uint8 kNoteOn[] = { 0x90, 0x3c, 0x7f };
23 const uint8 kNoteOnWithRunningStatus[] = {
24 0x90, 0x3c, 0x7f, 0x3c, 0x7f, 0x3c, 0x7f,
26 const uint8 kChannelPressure[] = { 0xd0, 0x01 };
27 const uint8 kChannelPressureWithRunningStatus[] = {
28 0xd0, 0x01, 0x01, 0x01,
30 const uint8 kTimingClock[] = { 0xf8 };
31 const uint8 kBrokenData1[] = { 0x90 };
32 const uint8 kBrokenData2[] = { 0xf7 };
33 const uint8 kBrokenData3[] = { 0xf2, 0x00 };
34 const uint8 kDataByte0[] = { 0x00 };
36 const int kRenderProcessId = 0;
38 template <typename T, size_t N>
39 const std::vector<T> AsVector(const T(&data)[N]) {
40 std::vector<T> buffer;
41 buffer.insert(buffer.end(), data, data + N);
42 return buffer;
45 template <typename T, size_t N>
46 void PushToVector(const T(&data)[N], std::vector<T>* buffer) {
47 buffer->insert(buffer->end(), data, data + N);
50 enum MidiEventType {
51 DISPATCH_SEND_MIDI_DATA,
54 struct MidiEvent {
55 MidiEvent(MidiEventType in_type,
56 uint32 in_port_index,
57 const std::vector<uint8>& in_data,
58 double in_timestamp)
59 : type(in_type),
60 port_index(in_port_index),
61 data(in_data),
62 timestamp(in_timestamp) {}
64 MidiEventType type;
65 uint32 port_index;
66 std::vector<uint8> data;
67 double timestamp;
70 class FakeMidiManager : public media::MidiManager {
71 public:
72 void DispatchSendMidiData(media::MidiManagerClient* client,
73 uint32 port_index,
74 const std::vector<uint8>& data,
75 double timestamp) override {
76 events_.push_back(MidiEvent(DISPATCH_SEND_MIDI_DATA,
77 port_index,
78 data,
79 timestamp));
81 std::vector<MidiEvent> events_;
84 class MidiHostForTesting : public MidiHost {
85 public:
86 MidiHostForTesting(int renderer_process_id, media::MidiManager* midi_manager)
87 : MidiHost(renderer_process_id, midi_manager) {}
89 private:
90 ~MidiHostForTesting() override {}
92 // BrowserMessageFilter implementation.
93 // Override BadMessageReceived() so to do nothing since the original
94 // implementation to kill a malicious renderer process causes a check failure
95 // in unit tests.
96 void BadMessageReceived() override {}
99 class MidiHostTest : public testing::Test {
100 public:
101 MidiHostTest()
102 : io_browser_thread_(BrowserThread::IO, &message_loop_),
103 host_(new MidiHostForTesting(kRenderProcessId, &manager_)),
104 data_(kNoteOn, kNoteOn + arraysize(kNoteOn)),
105 port_id_(0) {}
107 protected:
108 void AddOutputPort() {
109 const std::string id = base::StringPrintf("i-can-%d", port_id_++);
110 const std::string manufacturer("yukatan");
111 const std::string name("doki-doki-pi-pine");
112 const std::string version("3.14159265359");
113 media::MidiPortState state = media::MIDI_PORT_CONNECTED;
114 media::MidiPortInfo info(id, manufacturer, name, version, state);
116 host_->AddOutputPort(info);
119 void OnSendData(uint32 port) {
120 scoped_ptr<IPC::Message> message(
121 new MidiHostMsg_SendData(port, data_, 0.0));
122 host_->OnMessageReceived(*message.get());
125 size_t GetEventSize() const {
126 return manager_.events_.size();
129 void CheckSendEventAt(size_t at, uint32 port) {
130 EXPECT_EQ(DISPATCH_SEND_MIDI_DATA, manager_.events_[at].type);
131 EXPECT_EQ(port, manager_.events_[at].port_index);
132 EXPECT_EQ(data_, manager_.events_[at].data);
133 EXPECT_EQ(0.0, manager_.events_[at].timestamp);
136 void RunLoopUntilIdle() {
137 base::RunLoop run_loop;
138 run_loop.RunUntilIdle();
141 private:
142 base::MessageLoop message_loop_;
143 TestBrowserThread io_browser_thread_;
145 FakeMidiManager manager_;
146 scoped_refptr<MidiHostForTesting> host_;
147 std::vector<uint8> data_;
148 int32 port_id_;
150 DISALLOW_COPY_AND_ASSIGN(MidiHostTest);
153 } // namespace
155 TEST_F(MidiHostTest, IsValidWebMIDIData) {
156 // Test single event scenario
157 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kGMOn)));
158 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kGSOn)));
159 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kNoteOn)));
160 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kChannelPressure)));
161 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kTimingClock)));
162 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kBrokenData1)));
163 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kBrokenData2)));
164 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kBrokenData3)));
165 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kDataByte0)));
167 // MIDI running status should be disallowed
168 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(
169 AsVector(kNoteOnWithRunningStatus)));
170 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(
171 AsVector(kChannelPressureWithRunningStatus)));
173 // Multiple messages are allowed as long as each of them is complete.
175 std::vector<uint8> buffer;
176 PushToVector(kGMOn, &buffer);
177 PushToVector(kNoteOn, &buffer);
178 PushToVector(kGSOn, &buffer);
179 PushToVector(kTimingClock, &buffer);
180 PushToVector(kNoteOn, &buffer);
181 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(buffer));
182 PushToVector(kBrokenData1, &buffer);
183 EXPECT_FALSE(MidiHost::IsValidWebMIDIData(buffer));
186 // MIDI realtime message can be placed at any position.
188 const uint8 kNoteOnWithRealTimeClock[] = {
189 0x90, 0xf8, 0x3c, 0x7f, 0x90, 0xf8, 0x3c, 0xf8, 0x7f, 0xf8,
191 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(
192 AsVector(kNoteOnWithRealTimeClock)));
194 const uint8 kGMOnWithRealTimeClock[] = {
195 0xf0, 0xf8, 0x7e, 0x7f, 0x09, 0x01, 0xf8, 0xf7,
197 EXPECT_TRUE(MidiHost::IsValidWebMIDIData(
198 AsVector(kGMOnWithRealTimeClock)));
202 // Test if sending data to out of range port is ignored.
203 TEST_F(MidiHostTest, OutputPortCheck) {
204 // Only one output port is available.
205 AddOutputPort();
207 // Sending data to port 0 should be delivered.
208 uint32 port0 = 0;
209 OnSendData(port0);
210 RunLoopUntilIdle();
211 EXPECT_EQ(1U, GetEventSize());
212 CheckSendEventAt(0, port0);
214 // Sending data to port 1 should not be delivered.
215 uint32 port1 = 1;
216 OnSendData(port1);
217 RunLoopUntilIdle();
218 EXPECT_EQ(1U, GetEventSize());
220 // Two output ports are available from now on.
221 AddOutputPort();
223 // Sending data to port 0 and 1 should be delivered now.
224 OnSendData(port0);
225 OnSendData(port1);
226 RunLoopUntilIdle();
227 EXPECT_EQ(3U, GetEventSize());
228 CheckSendEventAt(1, port0);
229 CheckSendEventAt(2, port1);
232 } // namespace conent