Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / midi / midi_manager_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.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace media {
18
19 namespace {
20
21 class FakeMidiManager : public MidiManager {
22  public:
23   FakeMidiManager() : start_initialization_is_called_(false) {}
24   ~FakeMidiManager() override {}
25
26   // MidiManager implementation.
27   void StartInitialization() override {
28     start_initialization_is_called_ = true;
29   }
30
31   void DispatchSendMidiData(MidiManagerClient* client,
32                             uint32 port_index,
33                             const std::vector<uint8>& data,
34                             double timestamp) override {}
35
36   // Utility functions for testing.
37   void CallCompleteInitialization(MidiResult result) {
38     CompleteInitialization(result);
39   }
40
41   size_t GetClientCount() const {
42     return clients_size_for_testing();
43   }
44
45   size_t GetPendingClientCount() const {
46     return pending_clients_size_for_testing();
47   }
48
49   bool start_initialization_is_called_;
50
51  private:
52   DISALLOW_COPY_AND_ASSIGN(FakeMidiManager);
53 };
54
55 class FakeMidiManagerClient : public MidiManagerClient {
56  public:
57   FakeMidiManagerClient()
58       : result_(MIDI_NOT_SUPPORTED),
59         wait_for_result_(true) {}
60   ~FakeMidiManagerClient() override {}
61
62   // MidiManagerClient implementation.
63   void AddInputPort(const MidiPortInfo& info) override {}
64   void AddOutputPort(const MidiPortInfo& info) override {}
65
66   void CompleteStartSession(MidiResult result) override {
67     EXPECT_TRUE(wait_for_result_);
68     result_ = result;
69     wait_for_result_ = false;
70   }
71
72   void ReceiveMidiData(uint32 port_index,
73                        const uint8* data,
74                        size_t size,
75                        double timestamp) override {}
76   void AccumulateMidiBytesSent(size_t size) override {}
77
78   MidiResult result() const { return result_; }
79
80   MidiResult WaitForResult() {
81     while (wait_for_result_) {
82       base::RunLoop run_loop;
83       run_loop.RunUntilIdle();
84     }
85     return result();
86   }
87
88  private:
89   MidiResult result_;
90   bool wait_for_result_;
91
92   DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient);
93 };
94
95 class MidiManagerTest : public ::testing::Test {
96  public:
97   MidiManagerTest()
98       : manager_(new FakeMidiManager),
99         message_loop_(new base::MessageLoop) {}
100   ~MidiManagerTest() override {}
101
102  protected:
103   void StartTheFirstSession(FakeMidiManagerClient* client) {
104     EXPECT_FALSE(manager_->start_initialization_is_called_);
105     EXPECT_EQ(0U, manager_->GetClientCount());
106     EXPECT_EQ(0U, manager_->GetPendingClientCount());
107     manager_->StartSession(client);
108     EXPECT_EQ(0U, manager_->GetClientCount());
109     EXPECT_EQ(1U, manager_->GetPendingClientCount());
110     EXPECT_TRUE(manager_->start_initialization_is_called_);
111     EXPECT_EQ(0U, manager_->GetClientCount());
112     EXPECT_EQ(1U, manager_->GetPendingClientCount());
113     EXPECT_TRUE(manager_->start_initialization_is_called_);
114   }
115
116   void StartTheNthSession(FakeMidiManagerClient* client, size_t nth) {
117     EXPECT_EQ(nth != 1, manager_->start_initialization_is_called_);
118     EXPECT_EQ(0U, manager_->GetClientCount());
119     EXPECT_EQ(nth - 1, manager_->GetPendingClientCount());
120
121     // StartInitialization() should not be called for the second and later
122     // sessions.
123     manager_->start_initialization_is_called_ = false;
124     manager_->StartSession(client);
125     EXPECT_EQ(nth == 1, manager_->start_initialization_is_called_);
126     manager_->start_initialization_is_called_ = true;
127   }
128
129   void EndSession(FakeMidiManagerClient* client, size_t before, size_t after) {
130     EXPECT_EQ(before, manager_->GetClientCount());
131     manager_->EndSession(client);
132     EXPECT_EQ(after, manager_->GetClientCount());
133   }
134
135   void CompleteInitialization(MidiResult result) {
136     manager_->CallCompleteInitialization(result);
137   }
138
139   void RunLoopUntilIdle() {
140     base::RunLoop run_loop;
141     run_loop.RunUntilIdle();
142   }
143
144  protected:
145   scoped_ptr<FakeMidiManager> manager_;
146
147  private:
148   scoped_ptr<base::MessageLoop> message_loop_;
149
150   DISALLOW_COPY_AND_ASSIGN(MidiManagerTest);
151 };
152
153 TEST_F(MidiManagerTest, StartAndEndSession) {
154   scoped_ptr<FakeMidiManagerClient> client;
155   client.reset(new FakeMidiManagerClient);
156
157   StartTheFirstSession(client.get());
158   CompleteInitialization(MIDI_OK);
159   EXPECT_EQ(MIDI_OK, client->WaitForResult());
160   EndSession(client.get(), 1U, 0U);
161 }
162
163 TEST_F(MidiManagerTest, StartAndEndSessionWithError) {
164   scoped_ptr<FakeMidiManagerClient> client;
165   client.reset(new FakeMidiManagerClient);
166
167   StartTheFirstSession(client.get());
168   CompleteInitialization(MIDI_INITIALIZATION_ERROR);
169   EXPECT_EQ(MIDI_INITIALIZATION_ERROR, client->WaitForResult());
170   EndSession(client.get(), 0U, 0U);
171 }
172
173 TEST_F(MidiManagerTest, StartMultipleSessions) {
174   scoped_ptr<FakeMidiManagerClient> client1;
175   scoped_ptr<FakeMidiManagerClient> client2;
176   scoped_ptr<FakeMidiManagerClient> client3;
177   client1.reset(new FakeMidiManagerClient);
178   client2.reset(new FakeMidiManagerClient);
179   client3.reset(new FakeMidiManagerClient);
180
181   StartTheFirstSession(client1.get());
182   StartTheNthSession(client2.get(), 2);
183   StartTheNthSession(client3.get(), 3);
184   CompleteInitialization(MIDI_OK);
185   EXPECT_EQ(MIDI_OK, client1->WaitForResult());
186   EXPECT_EQ(MIDI_OK, client2->WaitForResult());
187   EXPECT_EQ(MIDI_OK, client3->WaitForResult());
188   EndSession(client1.get(), 3U, 2U);
189   EndSession(client2.get(), 2U, 1U);
190   EndSession(client3.get(), 1U, 0U);
191 }
192
193 // TODO(toyoshim): Add a test for a MidiManagerClient that has multiple
194 // sessions with multiple client_id.
195
196 TEST_F(MidiManagerTest, TooManyPendingSessions) {
197   // Push as many client requests for starting session as possible.
198   ScopedVector<FakeMidiManagerClient> many_existing_clients;
199   many_existing_clients.resize(MidiManager::kMaxPendingClientCount);
200   for (size_t i = 0; i < MidiManager::kMaxPendingClientCount; ++i) {
201     many_existing_clients[i] = new FakeMidiManagerClient;
202     StartTheNthSession(many_existing_clients[i], i + 1);
203   }
204
205   // Push the last client that should be rejected for too many pending requests.
206   scoped_ptr<FakeMidiManagerClient> additional_client(
207       new FakeMidiManagerClient);
208   manager_->start_initialization_is_called_ = false;
209   manager_->StartSession(additional_client.get());
210   EXPECT_FALSE(manager_->start_initialization_is_called_);
211   EXPECT_EQ(MIDI_INITIALIZATION_ERROR, additional_client->result());
212
213   // Other clients still should not receive a result.
214   RunLoopUntilIdle();
215   for (size_t i = 0; i < many_existing_clients.size(); ++i)
216     EXPECT_EQ(MIDI_NOT_SUPPORTED, many_existing_clients[i]->result());
217
218   // The result MIDI_OK should be distributed to other clients.
219   CompleteInitialization(MIDI_OK);
220   for (size_t i = 0; i < many_existing_clients.size(); ++i)
221     EXPECT_EQ(MIDI_OK, many_existing_clients[i]->WaitForResult());
222
223   // Close all successful sessions in FIFO order.
224   size_t sessions = many_existing_clients.size();
225   for (size_t i = 0; i < many_existing_clients.size(); ++i, --sessions)
226     EndSession(many_existing_clients[i], sessions, sessions - 1);
227 }
228
229 TEST_F(MidiManagerTest, AbortSession) {
230   // A client starting a session can be destructed while an asynchronous
231   // initialization is performed.
232   scoped_ptr<FakeMidiManagerClient> client;
233   client.reset(new FakeMidiManagerClient);
234
235   StartTheFirstSession(client.get());
236   EndSession(client.get(), 0, 0);
237   client.reset();
238
239   // Following function should not call the destructed |client| function.
240   CompleteInitialization(MIDI_OK);
241   base::RunLoop run_loop;
242   run_loop.RunUntilIdle();
243 }
244
245 TEST_F(MidiManagerTest, CreateMidiManager) {
246   scoped_ptr<FakeMidiManagerClient> client;
247   client.reset(new FakeMidiManagerClient);
248
249   scoped_ptr<MidiManager> manager(MidiManager::Create());
250   manager->StartSession(client.get());
251
252   MidiResult result = client->WaitForResult();
253   // This #ifdef needs to be identical to the one in media/midi/midi_manager.cc.
254   // Do not change the condition for disabling this test.
255 #if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \
256     !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
257   EXPECT_EQ(MIDI_NOT_SUPPORTED, result);
258 #elif defined(USE_ALSA)
259   // Temporary until http://crbug.com/371230 is resolved.
260   EXPECT_TRUE((result == MIDI_OK) || (result == MIDI_INITIALIZATION_ERROR));
261 #else
262   EXPECT_EQ(MIDI_OK, result);
263 #endif
264 }
265
266 }  // namespace
267
268 }  // namespace media