OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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 "platform/audio/PushPullFIFO.h" | |
6 | |
7 #include "platform/audio/AudioUtilities.h" | |
8 #include "platform/testing/TestingPlatformSupport.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 #include "wtf/PtrUtil.h" | |
11 #include <memory> | |
12 #include <vector> | |
13 | |
14 namespace blink { | |
15 | |
16 namespace { | |
17 | |
18 // Check the basic contract of FIFO. | |
19 TEST(PushPullFIFOBasicTest, BasicTests) { | |
20 // This suppresses the multi-thread warning for GTest. Potently it increases | |
21 // the test execution time, but this specific test is very short and simple. | |
22 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | |
23 | |
24 // FIFO length exceeding the maximum length allowed will cause crash. | |
25 EXPECT_DEATH(new PushPullFIFO(2, kMaxFIFOLength + 1), | |
26 "m_fifoLength <= kMaxFIFOLength"); | |
27 | |
28 std::unique_ptr<PushPullFIFO> testFifo = | |
29 WTF::wrapUnique(new PushPullFIFO(2, 1024)); | |
30 | |
31 // The input bus length must be |AudioUtilities::kRenderQuantumFrames|. | |
32 RefPtr<AudioBus> inputBusOf129Frames = | |
33 AudioBus::create(2, AudioUtilities::kRenderQuantumFrames + 1); | |
34 EXPECT_DEATH(testFifo->push(inputBusOf129Frames.get()), | |
35 "inputBus->length.* == .*kRenderQuantumFrames"); | |
36 RefPtr<AudioBus> inputBusOf127Frames = | |
37 AudioBus::create(2, AudioUtilities::kRenderQuantumFrames - 1); | |
38 EXPECT_DEATH(testFifo->push(inputBusOf127Frames.get()), | |
39 "inputBus->length.* == .*kRenderQuantumFrames"); | |
40 | |
41 // Pull request frames cannot exceed the length of output bus. | |
42 RefPtr<AudioBus> outputBusOf512Frames = AudioBus::create(2, 512); | |
43 EXPECT_DEATH(testFifo->pull(outputBusOf512Frames.get(), 513), | |
44 "framesRequested <= outputBus->length.*"); | |
45 | |
46 // Pull request frames cannot exceed the length of FIFO. | |
47 RefPtr<AudioBus> outputBusOf1025Frames = AudioBus::create(2, 1025); | |
48 EXPECT_DEATH(testFifo->pull(outputBusOf1025Frames.get(), 1025), | |
49 "framesRequested <= m_fifoLength"); | |
50 } | |
51 | |
52 // Fills each AudioChannel in an AudioBus with a series of linearly increasing | |
53 // values starting from |startingValue| and incrementing by 1. Then return value | |
54 // will be |startingValue| + |bus_length|. | |
55 size_t fillBusWithLinearRamp(AudioBus* targetBus, size_t startingValue) { | |
56 for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { | |
57 float* busChannel = targetBus->channel(c)->mutableData(); | |
58 for (size_t i = 0; i < targetBus->channel(c)->length(); ++i) { | |
59 busChannel[i] = static_cast<float>(startingValue + i); | |
60 } | |
61 } | |
62 return startingValue + targetBus->length(); | |
63 } | |
64 | |
65 // Inspect the content of AudioBus with a given set of index and value across | |
66 // channels. | |
67 bool verifyBusValueAtIndex(AudioBus* targetBus, | |
68 int index, | |
69 float expectedValue) { | |
70 for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { | |
71 float* busChannel = targetBus->channel(c)->mutableData(); | |
72 if (busChannel[index] != expectedValue) { | |
73 LOG(ERROR) << ">> [FAIL] expected " << expectedValue << " at index " | |
74 << index << " but got " << busChannel[index] << "."; | |
75 return false; | |
76 } | |
77 } | |
78 return true; | |
79 } | |
80 | |
81 struct FIFOAction { | |
82 // The type of action; "PUSH" or "PULL". | |
83 const char* action; | |
84 // Number of frames for the operation. | |
85 const size_t numberOfFrames; | |
86 }; | |
87 | |
88 struct AudioBusSample { | |
89 // The frame index of a sample in the bus. | |
90 const size_t index; | |
91 // The value at the |index| above. | |
92 const float value; | |
93 }; | |
94 | |
95 struct FIFOTestSetup { | |
96 // Length of FIFO to be created for test case. | |
97 const size_t fifoLength; | |
98 // Channel count of FIFO to be created for test case. | |
99 const unsigned numberOfChannels; | |
100 // A list of |FIFOAction| entries to be performed in test case. | |
101 const std::vector<FIFOAction> fifoActions; | |
102 }; | |
103 | |
104 struct FIFOTestExpectedState { | |
105 // Expected read index in FIFO. | |
106 const size_t indexRead; | |
107 // Expected write index in FIFO. | |
108 const size_t indexWrite; | |
109 // Expected overflow count in FIFO. | |
110 const unsigned overflowCount; | |
111 // Expected underflow count in FIFO. | |
112 const unsigned underflowCount; | |
113 // A list of expected |AudioBusSample| entries for the FIFO bus. | |
114 const std::vector<AudioBusSample> fifoSamples; | |
115 // A list of expected |AudioBusSample| entries for the output bus. | |
116 const std::vector<AudioBusSample> outputSamples; | |
117 }; | |
118 | |
119 // The data structure for the parameterized test cases. | |
120 struct FIFOTestParam { | |
121 FIFOTestSetup setup; | |
122 FIFOTestExpectedState expectedState; | |
123 }; | |
124 | |
125 std::ostream& operator<<(std::ostream& out, const FIFOTestParam& param) { | |
126 out << "fifoLength=" << param.setup.fifoLength | |
127 << " numberOfChannels=" << param.setup.numberOfChannels; | |
128 return out; | |
129 } | |
130 | |
131 class PushPullFIFOFeatureTest : public ::testing::TestWithParam<FIFOTestParam> { | |
132 }; | |
133 | |
134 TEST_P(PushPullFIFOFeatureTest, FeatureTests) { | |
135 const FIFOTestSetup setup = GetParam().setup; | |
136 const FIFOTestExpectedState expectedState = GetParam().expectedState; | |
137 | |
138 // Create a FIFO with a specified configuration. | |
139 std::unique_ptr<PushPullFIFO> fifo = WTF::wrapUnique( | |
140 new PushPullFIFO(setup.numberOfChannels, setup.fifoLength)); | |
141 | |
142 RefPtr<AudioBus> outputBus; | |
143 | |
144 // Iterate all the scheduled push/pull actions. | |
145 size_t frameCounter = 0; | |
146 for (const auto& action : setup.fifoActions) { | |
147 if (strcmp(action.action, "PUSH") == 0) { | |
148 RefPtr<AudioBus> inputBus = | |
149 AudioBus::create(setup.numberOfChannels, action.numberOfFrames); | |
150 frameCounter = fillBusWithLinearRamp(inputBus.get(), frameCounter); | |
151 fifo->push(inputBus.get()); | |
152 LOG(INFO) << "PUSH " << action.numberOfFrames | |
153 << " frames (frameCounter=" << frameCounter << ")"; | |
154 } else { | |
155 outputBus = | |
156 AudioBus::create(setup.numberOfChannels, action.numberOfFrames); | |
157 fifo->pull(outputBus.get(), action.numberOfFrames); | |
158 LOG(INFO) << "PULL " << action.numberOfFrames << " frames"; | |
159 } | |
160 } | |
161 | |
162 // Get FIFO config data. | |
163 const PushPullFIFOStateForTest actualState = fifo->getStateForTest(); | |
164 | |
165 // Verify the read/write indexes. | |
166 EXPECT_EQ(expectedState.indexRead, actualState.indexRead); | |
167 EXPECT_EQ(expectedState.indexWrite, actualState.indexWrite); | |
168 EXPECT_EQ(expectedState.overflowCount, actualState.overflowCount); | |
169 EXPECT_EQ(expectedState.underflowCount, actualState.underflowCount); | |
170 | |
171 // Verify in-FIFO samples. | |
172 for (const auto& sample : expectedState.fifoSamples) { | |
173 EXPECT_TRUE(verifyBusValueAtIndex(fifo->bus(), sample.index, sample.value)); | |
174 } | |
175 | |
176 // Verify samples from the most recent output bus. | |
177 for (const auto& sample : expectedState.outputSamples) { | |
178 EXPECT_TRUE( | |
179 verifyBusValueAtIndex(outputBus.get(), sample.index, sample.value)); | |
180 } | |
181 } | |
182 | |
183 FIFOTestParam featureTestParams[] = { | |
184 // Test cases 0 ~ 3: Regular operation on various channel configuration. | |
185 // - Mono, Stereo, Quad, 5.1. | |
186 // - FIFO length and pull size are RQ-aligned. | |
187 {{512, 1, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}}, | |
188 {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}}, | |
189 | |
190 {{512, 2, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}}, | |
191 {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}}, | |
192 | |
193 {{512, 4, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}}, | |
194 {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}}, | |
195 | |
196 {{512, 6, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}}, | |
197 {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}}, | |
198 | |
199 // Test case 4: Unusual FIFO and Pull length. | |
200 // - FIFO and pull length that are not RQ-aligned. | |
201 // - Check if the indexes are wrapping around correctly. | |
202 // - Check if the output bus starts and ends with correct values. | |
203 {{997, | |
204 1, | |
205 { | |
206 {"PUSH", 128}, | |
207 {"PUSH", 128}, | |
208 {"PUSH", 128}, | |
209 {"PUSH", 128}, | |
210 {"PULL", 449}, | |
211 {"PUSH", 128}, | |
212 {"PUSH", 128}, | |
213 {"PUSH", 128}, | |
214 {"PUSH", 128}, | |
215 {"PULL", 449}, | |
216 }}, | |
217 {898, 27, 0, 0, {{898, 898}, {27, 27}}, {{0, 449}, {448, 897}}}}, | |
o1ka
2017/02/02 16:30:25
These values require comments, otherwise it;s real
hongchan
2017/02/02 19:55:23
Done.
| |
218 | |
219 // Test case 5: Overflow | |
220 // - Check overflow counter. | |
221 // - After the overflow occurs, the read index must be moved to the write | |
222 // index. Thus pulled frames must not contain overwritten data. | |
223 {{512, | |
224 3, | |
225 { | |
226 {"PUSH", 128}, | |
227 {"PUSH", 128}, | |
228 {"PUSH", 128}, | |
229 {"PUSH", 128}, | |
230 {"PUSH", 128}, | |
231 {"PULL", 256}, | |
232 }}, | |
233 {384, 128, 1, 0, {{384, 384}, {128, 128}}, {{0, 128}, {255, 383}}}}, | |
234 | |
235 // Test case 6: Overflow in unusual FIFO and pull length. | |
236 // - Check overflow counter. | |
237 // - After the overflow occurs, the read index must be moved to the write | |
238 // index. Thus pulled frames must not contain overwritten data. | |
239 {{577, | |
240 5, | |
241 { | |
242 {"PUSH", 128}, | |
243 {"PUSH", 128}, | |
244 {"PUSH", 128}, | |
245 {"PUSH", 128}, | |
246 {"PUSH", 128}, | |
247 {"PULL", 227}, | |
248 }}, | |
249 {290, 63, 1, 0, {{63, 63}, {290, 290}}, {{0, 63}, {226, 289}}}}, | |
250 | |
251 // Test case 7: Underflow | |
252 // - Check underflow counter. | |
253 // - After the underflow occurs, the write index must be moved to the read | |
254 // index. Frames pulled after FIFO underflows must be zeroed. | |
255 {{512, | |
256 7, | |
257 { | |
258 {"PUSH", 128}, | |
259 {"PUSH", 128}, | |
260 {"PUSH", 128}, | |
261 {"PULL", 384}, | |
262 {"PUSH", 128}, | |
263 {"PUSH", 128}, | |
264 {"PULL", 384}, | |
265 }}, | |
266 {128, | |
267 128, | |
268 0, | |
269 1, | |
270 {{128, 128}}, | |
271 {{0, 384}, {255, 639}, {256, 0}, {383, 0}}}}, | |
272 | |
273 // Test case 8: Underflow in unusual FIFO and pull length. | |
274 // - Check underflow counter. | |
275 // - After the underflow occurs, the write index must be moved to the read | |
276 // index. Frames pulled after FIFO underflows must be zeroed. | |
277 {{523, | |
278 11, | |
279 { | |
280 {"PUSH", 128}, | |
281 {"PUSH", 128}, | |
282 {"PUSH", 128}, | |
283 {"PULL", 383}, | |
284 {"PUSH", 128}, | |
285 {"PUSH", 128}, | |
286 {"PULL", 383}, | |
287 }}, | |
288 {117, | |
289 117, | |
290 0, | |
291 1, | |
292 {{117, 117}}, | |
293 {{0, 383}, {256, 639}, {257, 0}, {382, 0}}}}}; | |
o1ka
2017/02/02 16:30:25
Another corner case to consider: Multiple pulls fr
hongchan
2017/02/02 19:55:23
Done.
o1ka
2017/02/03 10:41:17
Right, but how about starting with Pull, without a
hongchan
2017/02/03 17:20:12
I'll add another for this case. Done.
| |
294 | |
295 INSTANTIATE_TEST_CASE_P(PushPullFIFOFeatureTest, | |
296 PushPullFIFOFeatureTest, | |
297 ::testing::ValuesIn(featureTestParams)); | |
298 | |
299 } // namespace | |
300 | |
301 } // namespace blink | |
OLD | NEW |