blob: 846e1bcfe64b8ef5f7c00e4af697328e9e679880 [file] [log] [blame]
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +00001// 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.h"
6
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +00007#include <vector>
8
toyoshimc9f52132014-10-15 05:50:07 -07009#include "base/bind.h"
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000010#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +000012#include "base/memory/scoped_vector.h"
toyoshimc9f52132014-10-15 05:50:07 -070013#include "base/message_loop/message_loop.h"
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000014#include "base/run_loop.h"
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000015#include "testing/gtest/include/gtest/gtest.h"
16
17namespace media {
18
19namespace {
20
21class FakeMidiManager : public MidiManager {
22 public:
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000023 FakeMidiManager() : start_initialization_is_called_(false) {}
dcheng63ccbc32014-10-21 05:23:27 -070024 ~FakeMidiManager() override {}
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000025
26 // MidiManager implementation.
dcheng63ccbc32014-10-21 05:23:27 -070027 void StartInitialization() override {
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000028 start_initialization_is_called_ = true;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000029 }
30
dcheng63ccbc32014-10-21 05:23:27 -070031 void DispatchSendMidiData(MidiManagerClient* client,
32 uint32 port_index,
33 const std::vector<uint8>& data,
34 double timestamp) override {}
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000035
36 // Utility functions for testing.
37 void CallCompleteInitialization(MidiResult result) {
38 CompleteInitialization(result);
39 }
40
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000041 size_t GetClientCount() const {
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +000042 return clients_size_for_testing();
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000043 }
44
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000045 size_t GetPendingClientCount() const {
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +000046 return pending_clients_size_for_testing();
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000047 }
48
49 bool start_initialization_is_called_;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000050
51 private:
52 DISALLOW_COPY_AND_ASSIGN(FakeMidiManager);
53};
54
55class FakeMidiManagerClient : public MidiManagerClient {
56 public:
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000057 explicit FakeMidiManagerClient(int client_id)
58 : client_id_(client_id),
59 result_(MIDI_NOT_SUPPORTED),
60 wait_for_result_(true) {}
dcheng63ccbc32014-10-21 05:23:27 -070061 ~FakeMidiManagerClient() override {}
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000062
63 // MidiManagerClient implementation.
dcheng63ccbc32014-10-21 05:23:27 -070064 void CompleteStartSession(int client_id, MidiResult result) override {
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +000065 EXPECT_TRUE(wait_for_result_);
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000066 CHECK_EQ(client_id_, client_id);
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000067 result_ = result;
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000068 wait_for_result_ = false;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000069 }
70
dcheng63ccbc32014-10-21 05:23:27 -070071 void ReceiveMidiData(uint32 port_index,
72 const uint8* data,
73 size_t size,
74 double timestamp) override {}
75 void AccumulateMidiBytesSent(size_t size) override {}
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000076
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +000077 int client_id() const { return client_id_; }
78 MidiResult result() const { return result_; }
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000079
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000080 MidiResult WaitForResult() {
toyoshim11f7d572014-10-20 02:37:10 -070081 while (wait_for_result_) {
82 base::RunLoop run_loop;
83 run_loop.RunUntilIdle();
84 }
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +000085 return result();
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000086 }
87
88 private:
89 int client_id_;
90 MidiResult result_;
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000091 bool wait_for_result_;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +000092
93 DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient);
94};
95
96class MidiManagerTest : public ::testing::Test {
97 public:
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +000098 MidiManagerTest()
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +000099 : manager_(new FakeMidiManager),
100 message_loop_(new base::MessageLoop) {}
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000101 virtual ~MidiManagerTest() {}
102
103 protected:
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000104 void StartTheFirstSession(FakeMidiManagerClient* client) {
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000105 EXPECT_FALSE(manager_->start_initialization_is_called_);
106 EXPECT_EQ(0U, manager_->GetClientCount());
107 EXPECT_EQ(0U, manager_->GetPendingClientCount());
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000108 manager_->StartSession(client, client->client_id());
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000109 EXPECT_EQ(0U, manager_->GetClientCount());
110 EXPECT_EQ(1U, manager_->GetPendingClientCount());
111 EXPECT_TRUE(manager_->start_initialization_is_called_);
112 EXPECT_EQ(0U, manager_->GetClientCount());
113 EXPECT_EQ(1U, manager_->GetPendingClientCount());
114 EXPECT_TRUE(manager_->start_initialization_is_called_);
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000115 }
116
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000117 void StartTheNthSession(FakeMidiManagerClient* client, size_t nth) {
118 EXPECT_EQ(nth != 1, manager_->start_initialization_is_called_);
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000119 EXPECT_EQ(0U, manager_->GetClientCount());
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000120 EXPECT_EQ(nth - 1, manager_->GetPendingClientCount());
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000121
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000122 // StartInitialization() should not be called for the second and later
123 // sessions.
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000124 manager_->start_initialization_is_called_ = false;
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000125 manager_->StartSession(client, client->client_id());
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000126 EXPECT_EQ(nth == 1, manager_->start_initialization_is_called_);
127 manager_->start_initialization_is_called_ = true;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000128 }
129
130 void EndSession(FakeMidiManagerClient* client, size_t before, size_t after) {
131 EXPECT_EQ(before, manager_->GetClientCount());
132 manager_->EndSession(client);
133 EXPECT_EQ(after, manager_->GetClientCount());
134 }
135
136 void CompleteInitialization(MidiResult result) {
137 manager_->CallCompleteInitialization(result);
138 }
139
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000140 void RunLoopUntilIdle() {
141 base::RunLoop run_loop;
142 run_loop.RunUntilIdle();
143 }
144
145 protected:
146 scoped_ptr<FakeMidiManager> manager_;
147
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000148 private:
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000149 scoped_ptr<base::MessageLoop> message_loop_;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000150
151 DISALLOW_COPY_AND_ASSIGN(MidiManagerTest);
152};
153
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000154TEST_F(MidiManagerTest, StartAndEndSession) {
155 scoped_ptr<FakeMidiManagerClient> client;
156 client.reset(new FakeMidiManagerClient(0));
157
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000158 StartTheFirstSession(client.get());
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000159 CompleteInitialization(MIDI_OK);
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000160 EXPECT_EQ(MIDI_OK, client->WaitForResult());
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000161 EndSession(client.get(), 1U, 0U);
162}
163
164TEST_F(MidiManagerTest, StartAndEndSessionWithError) {
165 scoped_ptr<FakeMidiManagerClient> client;
166 client.reset(new FakeMidiManagerClient(1));
167
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000168 StartTheFirstSession(client.get());
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000169 CompleteInitialization(MIDI_INITIALIZATION_ERROR);
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000170 EXPECT_EQ(MIDI_INITIALIZATION_ERROR, client->WaitForResult());
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000171 EndSession(client.get(), 0U, 0U);
172}
173
174TEST_F(MidiManagerTest, StartMultipleSessions) {
175 scoped_ptr<FakeMidiManagerClient> client1;
176 scoped_ptr<FakeMidiManagerClient> client2;
toyoshim@chromium.org1fa678a2014-06-13 09:40:33 +0000177 scoped_ptr<FakeMidiManagerClient> client3;
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000178 client1.reset(new FakeMidiManagerClient(0));
179 client2.reset(new FakeMidiManagerClient(1));
toyoshim@chromium.org1fa678a2014-06-13 09:40:33 +0000180 client3.reset(new FakeMidiManagerClient(1));
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000181
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000182 StartTheFirstSession(client1.get());
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000183 StartTheNthSession(client2.get(), 2);
toyoshim@chromium.org1fa678a2014-06-13 09:40:33 +0000184 StartTheNthSession(client3.get(), 3);
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000185 CompleteInitialization(MIDI_OK);
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000186 EXPECT_EQ(MIDI_OK, client1->WaitForResult());
187 EXPECT_EQ(MIDI_OK, client2->WaitForResult());
toyoshim@chromium.org1fa678a2014-06-13 09:40:33 +0000188 EXPECT_EQ(MIDI_OK, client3->WaitForResult());
189 EndSession(client1.get(), 3U, 2U);
190 EndSession(client2.get(), 2U, 1U);
191 EndSession(client3.get(), 1U, 0U);
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000192}
193
toyoshim@chromium.org1fa678a2014-06-13 09:40:33 +0000194// TODO(toyoshim): Add a test for a MidiManagerClient that has multiple
195// sessions with multiple client_id.
196
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000197TEST_F(MidiManagerTest, TooManyPendingSessions) {
198 // Push as many client requests for starting session as possible.
199 ScopedVector<FakeMidiManagerClient> many_existing_clients;
200 many_existing_clients.resize(MidiManager::kMaxPendingClientCount);
201 for (size_t i = 0; i < MidiManager::kMaxPendingClientCount; ++i) {
202 many_existing_clients[i] = new FakeMidiManagerClient(i);
203 StartTheNthSession(many_existing_clients[i], i + 1);
204 }
205
206 // Push the last client that should be rejected for too many pending requests.
207 scoped_ptr<FakeMidiManagerClient> additional_client(
208 new FakeMidiManagerClient(MidiManager::kMaxPendingClientCount));
209 manager_->start_initialization_is_called_ = false;
210 manager_->StartSession(additional_client.get(),
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000211 additional_client->client_id());
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000212 EXPECT_FALSE(manager_->start_initialization_is_called_);
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000213 EXPECT_EQ(MIDI_INITIALIZATION_ERROR, additional_client->result());
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000214
215 // Other clients still should not receive a result.
216 RunLoopUntilIdle();
217 for (size_t i = 0; i < many_existing_clients.size(); ++i)
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000218 EXPECT_EQ(MIDI_NOT_SUPPORTED, many_existing_clients[i]->result());
toyoshim@chromium.orgfc2002e2014-05-07 08:10:34 +0000219
220 // The result MIDI_OK should be distributed to other clients.
221 CompleteInitialization(MIDI_OK);
222 for (size_t i = 0; i < many_existing_clients.size(); ++i)
223 EXPECT_EQ(MIDI_OK, many_existing_clients[i]->WaitForResult());
224
225 // Close all successful sessions in FIFO order.
226 size_t sessions = many_existing_clients.size();
227 for (size_t i = 0; i < many_existing_clients.size(); ++i, --sessions)
228 EndSession(many_existing_clients[i], sessions, sessions - 1);
229}
230
toyoshim@chromium.org1fa678a2014-06-13 09:40:33 +0000231TEST_F(MidiManagerTest, AbortSession) {
232 // A client starting a session can be destructed while an asynchronous
233 // initialization is performed.
234 scoped_ptr<FakeMidiManagerClient> client;
235 client.reset(new FakeMidiManagerClient(0));
236
237 StartTheFirstSession(client.get());
238 EndSession(client.get(), 0, 0);
239 client.reset();
240
241 // Following function should not call the destructed |client| function.
242 CompleteInitialization(MIDI_OK);
243 base::RunLoop run_loop;
244 run_loop.RunUntilIdle();
245}
246
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000247TEST_F(MidiManagerTest, CreateMidiManager) {
248 scoped_ptr<FakeMidiManagerClient> client;
249 client.reset(new FakeMidiManagerClient(0));
250
251 scoped_ptr<MidiManager> manager(MidiManager::Create());
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000252 manager->StartSession(client.get(), client->client_id());
253
agoode@chromium.org25227512014-06-08 05:12:05 +0000254 MidiResult result = client->WaitForResult();
toyoshim@chromium.orga25e6832014-05-07 18:06:25 +0000255 // This #ifdef needs to be identical to the one in media/midi/midi_manager.cc.
256 // Do not change the condition for disabling this test.
dnicoara@chromium.orgc404df62014-05-06 22:56:00 +0000257#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \
258 !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
agoode@chromium.org25227512014-06-08 05:12:05 +0000259 EXPECT_EQ(MIDI_NOT_SUPPORTED, result);
260#elif defined(USE_ALSA)
261 // Temporary until http://crbug.com/371230 is resolved.
262 EXPECT_TRUE((result == MIDI_OK) || (result == MIDI_INITIALIZATION_ERROR));
dnicoara@chromium.orgc404df62014-05-06 22:56:00 +0000263#else
agoode@chromium.org25227512014-06-08 05:12:05 +0000264 EXPECT_EQ(MIDI_OK, result);
dnicoara@chromium.orgc404df62014-05-06 22:56:00 +0000265#endif
toyoshim@chromium.orgc1e05fb2014-05-06 16:39:20 +0000266}
267
toyoshim@chromium.org51c7f532014-05-01 17:17:32 +0000268} // namespace
269
270} // namespace media