Bug 1772053 - Enable dynamic code disable mitigations only on Windows 10 1703+ r...
[gecko.git] / dom / media / gtest / TestCubebInputStream.cpp
blob2b67106f037d87675399e14a225e8aef25a509c2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
7 #include "CubebInputStream.h"
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
12 #include "MockCubeb.h"
13 #include "WaitFor.h"
15 using namespace mozilla;
17 namespace {
18 #define DispatchFunction(f) \
19 NS_DispatchToCurrentThread(NS_NewRunnableFunction(__func__, f))
20 } // namespace
22 class MockListener : public CubebInputStream::Listener {
23 public:
24 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MockListener, override);
25 MOCK_METHOD2(DataCallback, long(const void* aBuffer, long aFrames));
26 MOCK_METHOD1(StateCallback, void(cubeb_state aState));
27 MOCK_METHOD0(DeviceChangedCallback, void());
29 private:
30 ~MockListener() = default;
33 TEST(TestCubebInputStream, DataCallback)
35 using ::testing::Ne;
36 using ::testing::NotNull;
38 MockCubeb* cubeb = new MockCubeb();
39 CubebUtils::ForceSetCubebContext(cubeb->AsCubebContext());
41 const CubebUtils::AudioDeviceID deviceId = nullptr;
42 const uint32_t channels = 2;
44 uint32_t rate = 0;
45 ASSERT_EQ(cubeb_get_preferred_sample_rate(cubeb->AsCubebContext(), &rate),
46 CUBEB_OK);
48 nsTArray<AudioDataValue> data;
49 auto listener = MakeRefPtr<MockListener>();
50 EXPECT_CALL(*listener, DataCallback(NotNull(), Ne(0)))
51 .WillRepeatedly([&](const void* aBuffer, long aFrames) {
52 const AudioDataValue* source =
53 reinterpret_cast<const AudioDataValue*>(aBuffer);
54 size_t sampleCount =
55 static_cast<size_t>(aFrames) * static_cast<size_t>(channels);
56 data.AppendElements(source, sampleCount);
57 return aFrames;
58 });
60 EXPECT_CALL(*listener, StateCallback(CUBEB_STATE_STARTED));
61 EXPECT_CALL(*listener, StateCallback(CUBEB_STATE_STOPPED));
63 EXPECT_CALL(*listener, DeviceChangedCallback).Times(0);
65 UniquePtr<CubebInputStream> cis;
66 DispatchFunction([&] {
67 cis = CubebInputStream::Create(deviceId, channels, rate, true,
68 listener.get());
69 ASSERT_TRUE(cis);
70 });
71 RefPtr<SmartMockCubebStream> stream = WaitFor(cubeb->StreamInitEvent());
72 EXPECT_TRUE(stream->mHasInput);
74 stream->SetInputRecordingEnabled(true);
76 DispatchFunction([&] { ASSERT_EQ(cis->Start(), CUBEB_OK); });
77 WaitFor(stream->FramesProcessedEvent());
79 DispatchFunction([&] { ASSERT_EQ(cis->Stop(), CUBEB_OK); });
80 WaitFor(stream->OutputVerificationEvent());
82 nsTArray<AudioDataValue> record = stream->TakeRecordedInput();
84 DispatchFunction([&] { cis = nullptr; });
85 WaitFor(cubeb->StreamDestroyEvent());
87 ASSERT_EQ(data, record);
90 TEST(TestCubebInputStream, ErrorCallback)
92 using ::testing::Ne;
93 using ::testing::NotNull;
94 using ::testing::ReturnArg;
96 MockCubeb* cubeb = new MockCubeb();
97 CubebUtils::ForceSetCubebContext(cubeb->AsCubebContext());
99 const CubebUtils::AudioDeviceID deviceId = nullptr;
100 const uint32_t channels = 2;
102 uint32_t rate = 0;
103 ASSERT_EQ(cubeb_get_preferred_sample_rate(cubeb->AsCubebContext(), &rate),
104 CUBEB_OK);
106 auto listener = MakeRefPtr<MockListener>();
107 EXPECT_CALL(*listener, DataCallback(NotNull(), Ne(0)))
108 .WillRepeatedly(ReturnArg<1>());
110 EXPECT_CALL(*listener, StateCallback(CUBEB_STATE_STARTED));
111 EXPECT_CALL(*listener, StateCallback(CUBEB_STATE_ERROR));
113 EXPECT_CALL(*listener, DeviceChangedCallback).Times(0);
115 UniquePtr<CubebInputStream> cis;
116 DispatchFunction([&] {
117 cis = CubebInputStream::Create(deviceId, channels, rate, true,
118 listener.get());
119 ASSERT_TRUE(cis);
121 RefPtr<SmartMockCubebStream> stream = WaitFor(cubeb->StreamInitEvent());
122 EXPECT_TRUE(stream->mHasInput);
124 DispatchFunction([&] { ASSERT_EQ(cis->Start(), CUBEB_OK); });
125 WaitFor(stream->FramesProcessedEvent());
127 DispatchFunction([&] { stream->ForceError(); });
128 WaitFor(stream->ErrorForcedEvent());
130 // If stream ran into an error state, then it should be stopped.
132 DispatchFunction([&] { cis = nullptr; });
133 WaitFor(cubeb->StreamDestroyEvent());
136 TEST(TestCubebInputStream, DeviceChangedCallback)
138 using ::testing::Ne;
139 using ::testing::NotNull;
140 using ::testing::ReturnArg;
142 MockCubeb* cubeb = new MockCubeb();
143 CubebUtils::ForceSetCubebContext(cubeb->AsCubebContext());
145 const CubebUtils::AudioDeviceID deviceId = nullptr;
146 const uint32_t channels = 2;
148 uint32_t rate = 0;
149 ASSERT_EQ(cubeb_get_preferred_sample_rate(cubeb->AsCubebContext(), &rate),
150 CUBEB_OK);
152 auto listener = MakeRefPtr<MockListener>();
153 EXPECT_CALL(*listener, DataCallback(NotNull(), Ne(0)))
154 .WillRepeatedly(ReturnArg<1>());
156 // In real world, the stream might run into an error state when the
157 // device-changed event is fired (e.g., the last default output device is
158 // unplugged). But it's fine to not check here since we can control how
159 // MockCubeb behaves.
160 EXPECT_CALL(*listener, StateCallback(CUBEB_STATE_STARTED));
161 EXPECT_CALL(*listener, StateCallback(CUBEB_STATE_STOPPED));
163 EXPECT_CALL(*listener, DeviceChangedCallback);
165 UniquePtr<CubebInputStream> cis;
166 DispatchFunction([&] {
167 cis = CubebInputStream::Create(deviceId, channels, rate, true,
168 listener.get());
169 ASSERT_TRUE(cis);
171 RefPtr<SmartMockCubebStream> stream = WaitFor(cubeb->StreamInitEvent());
172 EXPECT_TRUE(stream->mHasInput);
174 DispatchFunction([&] { ASSERT_EQ(cis->Start(), CUBEB_OK); });
175 WaitFor(stream->FramesProcessedEvent());
177 DispatchFunction([&] { stream->ForceDeviceChanged(); });
178 WaitFor(stream->DeviceChangeForcedEvent());
180 // The stream can keep running when its device is changed.
181 DispatchFunction([&] { ASSERT_EQ(cis->Stop(), CUBEB_OK); });
182 cubeb_state state = WaitFor(stream->StateEvent());
183 EXPECT_EQ(state, CUBEB_STATE_STOPPED);
185 DispatchFunction([&] { cis = nullptr; });
186 WaitFor(cubeb->StreamDestroyEvent());