1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "CubebUtils.h"
7 #include "GraphDriver.h"
8 
9 #include "gmock/gmock.h"
10 #include "gtest/gtest-printers.h"
11 #include "gtest/gtest.h"
12 
13 #include "mozilla/Attributes.h"
14 #include "mozilla/UniquePtr.h"
15 #include "nsTArray.h"
16 
17 #include "MockCubeb.h"
18 
19 using IterationResult = GraphInterface::IterationResult;
20 using ::testing::NiceMock;
21 using ::testing::Return;
22 using namespace mozilla;
23 
24 class MockGraphInterface : public GraphInterface {
25   NS_DECL_THREADSAFE_ISUPPORTS
26   MOCK_METHOD4(NotifyOutputData,
27                void(AudioDataValue*, size_t, TrackRate, uint32_t));
28   MOCK_METHOD0(NotifyStarted, void());
29   MOCK_METHOD4(NotifyInputData,
30                void(const AudioDataValue*, size_t, TrackRate, uint32_t));
31   MOCK_METHOD0(DeviceChanged, void());
32   /* OneIteration cannot be mocked because IterationResult is non-memmovable and
33    * cannot be passed as a parameter, which GMock does internally. */
OneIteration(GraphTime,GraphTime,AudioMixer *)34   IterationResult OneIteration(GraphTime, GraphTime, AudioMixer*) {
35     return mKeepProcessing ? IterationResult::CreateStillProcessing()
36                            : IterationResult::CreateStop(
37                                  NS_NewRunnableFunction(__func__, [] {}));
38   }
39 #ifdef DEBUG
InDriverIteration(GraphDriver * aDriver)40   bool InDriverIteration(GraphDriver* aDriver) override {
41     return aDriver->OnThread();
42   }
43 #endif
44 
StopIterating()45   void StopIterating() { mKeepProcessing = false; }
46 
47  protected:
48   Atomic<bool> mKeepProcessing{true};
49   virtual ~MockGraphInterface() = default;
50 };
51 
52 NS_IMPL_ISUPPORTS0(MockGraphInterface)
53 
TEST(TestAudioCallbackDriver,StartStop)54 TEST(TestAudioCallbackDriver, StartStop)
55 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
56   MockCubeb* cubeb = new MockCubeb();
57   CubebUtils::ForceSetCubebContext(cubeb->AsCubebContext());
58 
59   RefPtr<AudioCallbackDriver> driver;
60   auto graph = MakeRefPtr<NiceMock<MockGraphInterface>>();
61   EXPECT_CALL(*graph, NotifyStarted).Times(1);
62   ON_CALL(*graph, NotifyOutputData)
63       .WillByDefault([&](AudioDataValue*, size_t, TrackRate, uint32_t) {});
64 
65   driver = MakeRefPtr<AudioCallbackDriver>(graph, nullptr, 44100, 2, 0, nullptr,
66                                            nullptr, AudioInputType::Unknown);
67   EXPECT_FALSE(driver->ThreadRunning()) << "Verify thread is not running";
68   EXPECT_FALSE(driver->IsStarted()) << "Verify thread is not started";
69 
70   driver->Start();
71   // Allow some time to "play" audio.
72   std::this_thread::sleep_for(std::chrono::milliseconds(200));
73   EXPECT_TRUE(driver->ThreadRunning()) << "Verify thread is running";
74   EXPECT_TRUE(driver->IsStarted()) << "Verify thread is started";
75 
76   // This will block untill all events have been executed.
77   graph->StopIterating();
78   MOZ_KnownLive(driver)->Shutdown();
79   EXPECT_FALSE(driver->ThreadRunning()) << "Verify thread is not running";
80   EXPECT_FALSE(driver->IsStarted()) << "Verify thread is not started";
81 }
82