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, PushPullFIFO::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}}}, | |
o1ka
2017/02/03 10:41:17
Is FIFO length always proportional to 128? If not,
hongchan
2017/02/03 17:20:12
Many test cases below are using unusual FIFO lengt
| |
188 {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}}, | |
189 | |
190 {{512, 2, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}}, | |
o1ka
2017/02/03 10:41:17
Other corner cases: Pull [FIFO length] samples;
FI
hongchan
2017/02/03 17:20:12
Done.
| |
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}, | |
o1ka
2017/02/03 10:41:17
There are no tests here where PULL is smaller than
hongchan
2017/02/03 17:20:12
Done.
| |
211 {"PUSH", 128}, | |
212 {"PUSH", 128}, | |
213 {"PUSH", 128}, | |
214 {"PUSH", 128}, | |
215 {"PULL", 449}, | |
216 }}, | |
217 // - expectedIndexRead = 898, expectedIndexWrite = 27 | |
218 // - overflowCount = 0, underflowCount = 0 | |
219 // - FIFO samples (index, expectedValue) = (898, 898), (27, 27) | |
220 // - Output bus samples (index, expectedValue) = (0, 499), (448, 897) | |
221 {898, 27, 0, 0, {{898, 898}, {27, 27}}, {{0, 449}, {448, 897}}}}, | |
222 | |
223 // Test case 5: Overflow | |
224 // - Check overflow counter. | |
225 // - After the overflow occurs, the read index must be moved to the write | |
226 // index. Thus pulled frames must not contain overwritten data. | |
227 {{512, | |
228 3, | |
229 { | |
230 {"PUSH", 128}, | |
231 {"PUSH", 128}, | |
232 {"PUSH", 128}, | |
233 {"PUSH", 128}, | |
234 {"PUSH", 128}, | |
235 {"PULL", 256}, | |
236 }}, | |
237 // - expectedIndexRead = 384, expectedIndexWrite = 128 | |
238 // - overflowCount = 1, underflowCount = 0 | |
239 // - FIFO samples (index, expectedValue) = (384, 384), (128, 128) | |
240 // - Output bus samples (index, expectedValue) = (0, 128), (255, 383) | |
241 {384, 128, 1, 0, {{384, 384}, {128, 128}}, {{0, 128}, {255, 383}}}}, | |
242 | |
243 // Test case 6: Overflow in unusual FIFO and pull length. | |
244 // - Check overflow counter. | |
245 // - After the overflow occurs, the read index must be moved to the write | |
246 // index. Thus pulled frames must not contain overwritten data. | |
247 {{577, | |
248 5, | |
249 { | |
250 {"PUSH", 128}, | |
251 {"PUSH", 128}, | |
252 {"PUSH", 128}, | |
253 {"PUSH", 128}, | |
254 {"PUSH", 128}, | |
255 {"PULL", 227}, | |
256 }}, | |
257 // - expectedIndexRead = 290, expectedIndexWrite = 63 | |
258 // - overflowCount = 1, underflowCount = 0 | |
259 // - FIFO samples (index, expectedValue) = (63, 63), (290, 290) | |
260 // - Output bus samples (index, expectedValue) = (0, 63), (226, 289) | |
261 {290, 63, 1, 0, {{63, 63}, {290, 290}}, {{0, 63}, {226, 289}}}}, | |
262 | |
263 // Test case 7: Underflow | |
264 // - Check underflow counter. | |
265 // - After the underflow occurs, the write index must be moved to the read | |
266 // index. Frames pulled after FIFO underflows must be zeroed. | |
267 {{512, | |
268 7, | |
269 { | |
270 {"PUSH", 128}, | |
271 {"PUSH", 128}, | |
272 {"PUSH", 128}, | |
273 {"PULL", 384}, | |
274 {"PUSH", 128}, | |
275 {"PUSH", 128}, | |
276 {"PULL", 384}, | |
277 }}, | |
278 // - expectedIndexRead = 128, expectedIndexWrite = 128 | |
279 // - overflowCount = 0, underflowCount = 1 | |
280 // - FIFO samples (index, expectedValue) = (128, 128) | |
281 // - Output bus samples (index, expectedValue) = (0, 384), (255, 639) | |
282 // (256, 0), (383, 0) | |
283 {128, | |
284 128, | |
285 0, | |
286 1, | |
287 {{128, 128}}, | |
288 {{0, 384}, {255, 639}, {256, 0}, {383, 0}}}}, | |
289 | |
290 // Test case 8: Underflow in unusual FIFO and pull length. | |
291 // - Check underflow counter. | |
292 // - After the underflow occurs, the write index must be moved to the read | |
293 // index. Frames pulled after FIFO underflows must be zeroed. | |
294 {{523, | |
295 11, | |
296 { | |
297 {"PUSH", 128}, | |
298 {"PUSH", 128}, | |
299 {"PUSH", 128}, | |
300 {"PULL", 383}, | |
301 {"PUSH", 128}, | |
302 {"PUSH", 128}, | |
303 {"PULL", 383}, | |
304 }}, | |
305 // - expectedIndexRead = 117, expectedIndexWrite = 117 | |
306 // - overflowCount = 0, underflowCount = 1 | |
307 // - FIFO samples (index, expectedValue) = (117, 117) | |
308 // - Output bus samples (index, expectedValue) = (0, 383), (256, 639) | |
309 // (257, 0), (382, 0) | |
310 {117, | |
311 117, | |
312 0, | |
313 1, | |
314 {{117, 117}}, | |
315 {{0, 383}, {256, 639}, {257, 0}, {382, 0}}}}, | |
316 | |
317 // Test case 9: Multiple pull from an empty FIFO. | |
318 // - Check underflow counter. | |
319 // - After the underflow occurs, the write index must be moved to the read | |
320 // index. Frames pulled after FIFO underflows must be zeroed. | |
321 {{1024, | |
322 11, | |
323 { | |
324 {"PUSH", 128}, | |
325 {"PUSH", 128}, | |
326 {"PULL", 440}, | |
327 {"PULL", 440}, | |
328 {"PULL", 440}, | |
329 {"PULL", 440}, | |
330 {"PULL", 440}, | |
331 }}, | |
332 // - expectedIndexRead = 117, expectedIndexWrite = 117 | |
333 // - overflowCount = 0, underflowCount = 1 | |
334 // - FIFO samples (index, expectedValue) = (117, 117) | |
335 // - Output bus samples (index, expectedValue) = (0, 383), (256, 639) | |
336 // (257, 0), (382, 0) | |
337 {256, 256, 0, 5, {{256, 0}}, {{0, 0}, {439, 0}}}}}; | |
338 | |
339 INSTANTIATE_TEST_CASE_P(PushPullFIFOFeatureTest, | |
340 PushPullFIFOFeatureTest, | |
341 ::testing::ValuesIn(featureTestParams)); | |
342 | |
343 } // namespace | |
344 | |
345 } // namespace blink | |
OLD | NEW |