Chromium Code Reviews| Index: third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp |
| diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8fcf688bb1164031a29494e710f478d9aa415f72 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp |
| @@ -0,0 +1,180 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "platform/audio/PushPullFIFO.h" |
| + |
| +#include "platform/audio/AudioUtilities.h" |
| +#include "platform/testing/TestingPlatformSupport.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "wtf/PtrUtil.h" |
| +#include <memory> |
| +#include <vector> |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +// Fills each AudioChannel in an AudioBus with a series of linearly increasing |
| +// values starting from |startingValue|. Then return value will be |
|
Raymond Toy
2017/01/30 20:59:28
nit: "from |startingValue|" -> "from |startingValu
hongchan
2017/02/01 18:07:28
Done.
|
| +// |startingValue| + |bus_length|. |
| +size_t fillBusWithLinearRamp(AudioBus* targetBus, size_t startingValue) { |
| + for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { |
| + float* busChannel = targetBus->channel(c)->mutableData(); |
| + for (size_t i = 0; i < targetBus->channel(c)->length(); ++i) { |
| + busChannel[i] = static_cast<float>(startingValue + i); |
| + } |
| + } |
| + return startingValue + targetBus->length(); |
| +} |
| + |
| +// Inspect the content of AudioBus with a given set of index and value across |
| +// channels. |
| +bool verifyBusValueAtIndex(AudioBus* targetBus, |
| + int index, |
| + float expectedValue) { |
| + for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { |
| + float* busChannel = targetBus->channel(c)->mutableData(); |
| + if (busChannel[index] != expectedValue) { |
| + LOG(ERROR) << ">> [FAIL] expected " << expectedValue << " at index " |
| + << index << " but got " << busChannel[index] << "."; |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +struct FIFOAction { |
| + // The type of action; "PUSH" or "PULL". |
| + const char* type; |
|
Raymond Toy
2017/01/30 20:59:29
"type" is too generic. Maybe "action"?
hongchan
2017/02/01 18:07:28
Done.
|
| + // Number of frames for the operation. |
| + const size_t numberOfFrames; |
| +}; |
| + |
| +struct AudioBusSample { |
| + // The frame index of a sample in the bus. |
| + const size_t index; |
| + // The value at the |index| above. |
| + const float value; |
| +}; |
| + |
| +struct FIFOTestSetup { |
| + // Length of FIFO to be created for test case. |
| + const size_t fifoLength; |
| + // Channel count of FIFO to be created for test case. |
| + const unsigned numberOfChannels; |
| + // A list of |FIFOAction| entries to be performed in test case. |
| + const std::vector<FIFOAction> fifoActions; |
| +}; |
| + |
| +struct FIFOTestExpectedState { |
| + // Expected read index in FIFO. |
| + const size_t indexRead; |
| + // Expected write index in FIFO. |
| + const size_t indexWrite; |
| + // Expected overflow count in FIFO. |
| + const unsigned overflowCount; |
| + // Expected underflow count in FIFO. |
| + const unsigned underflowCount; |
| + // A list of expected |AudioBusSample| entries for the FIFO bus. |
| + const std::vector<AudioBusSample> fifoSamples; |
| + // A list of expected |AudioBusSample| entries for the output bus. |
| + const std::vector<AudioBusSample> outputSamples; |
| +}; |
| + |
| +// The data structure for the parameterized test cases. |
| +struct FIFOTestParam { |
| + FIFOTestSetup setup; |
| + FIFOTestExpectedState expectedState; |
| +}; |
| + |
| +std::ostream& operator<<(std::ostream& out, const FIFOTestParam& param) { |
| + out << "fifoLength=" << param.setup.fifoLength |
| + << "numberOfChannels=" << param.setup.numberOfChannels; |
| + return out; |
| +} |
| + |
| +FIFOTestParam basicFIFOTestParams[] = { |
| + |
| + // 1. Push 1024 frames first then pull 1024 frames. |
|
Raymond Toy
2017/01/30 20:59:29
How does this work? Or does this really mean you
|
| + {{8192, 2, {{"PUSH", 1024}, {"PULL", 1024}}}, |
| + {1024, 1024, 0, 0, {{1024, 0}}, {{0, 0}, {1023, 1023}}}}, |
| + |
| + // 2. Push 3 x 768 frames, then pull 1024 frames. 1 overflow should be |
| + // recorded and the wrap-around should happen correctly. Use odd channel |
|
Raymond Toy
2017/01/30 20:59:29
"odd" mean not even? Or "odd" meaning unusual? I
hongchan
2017/02/01 18:07:28
Done.
|
| + // count. |
| + {{2048, 3, {{"PUSH", 768}, {"PUSH", 768}, {"PUSH", 768}, {"PULL", 1024}}}, |
| + {1280, 256, 1, 0, {{255, 2303}, {256, 256}}, {{0, 256}, {1023, 1279}}}}, |
| + |
| + // 3. Push 512 frames and then pull 1024. Check if underflow occurs |
| + // correctly. Inspect the output bus content; the underflow will fill the |
| + // second half of the output bus silence. Use odd FIFO size. |
|
Raymond Toy
2017/01/30 20:59:28
If you're inspecting the output, you need a test c
hongchan
2017/02/01 18:07:28
All the verification in this test is done through
|
| + {{4096, 1, {{"PUSH", 512}, {"PULL", 1024}}}, |
| + {512, 512, 0, 1, {{512, 0}}, {{0, 0}, {511, 511}, {512, 0}, {1023, 0}}}}, |
| + |
| + // 4. Push 11, 324 frames. Then pull 11, 324 frames. The most recent output |
|
Raymond Toy
2017/01/30 20:59:28
Your contract said you can only push 128 frames.
hongchan
2017/02/01 18:07:28
This is to accommodate o1ka@'s suggestion. Now we
|
| + // must start from 11 and end with 323. Use odd FIFO size and channel |
| + // count. |
| + {{1234, 5, {{"PUSH", 11}, {"PUSH", 324}, {"PULL", 11}, {"PULL", 324}}}, |
| + {335, 335, 0, 0, {}, {{0, 11}, {323, 334}}}}}; |
| + |
| +class PushPullFIFOTest : public ::testing::TestWithParam<FIFOTestParam> {}; |
| + |
| +TEST_P(PushPullFIFOTest, BasicTests) { |
| + const FIFOTestSetup setup = GetParam().setup; |
| + const FIFOTestExpectedState expectedState = GetParam().expectedState; |
| + |
| + // Create a FIFO with a specified configuration. |
| + std::unique_ptr<PushPullFIFO> fifo = WTF::wrapUnique( |
| + new PushPullFIFO(setup.numberOfChannels, setup.fifoLength)); |
| + |
| + RefPtr<AudioBus> outputBus; |
| + |
| + // Iterate all the scheduled push/pull actions. |
| + size_t frameCounter = 0; |
| + for (const auto& action : setup.fifoActions) { |
| + if (strcmp(action.type, "PUSH") == 0) { |
| + RefPtr<AudioBus> inputBus = |
| + AudioBus::create(setup.numberOfChannels, action.numberOfFrames); |
| + frameCounter = fillBusWithLinearRamp(inputBus.get(), frameCounter); |
| + fifo->push(inputBus.get()); |
| + LOG(INFO) << "PUSH " << action.numberOfFrames |
| + << " frames (frameCounter=" << frameCounter << ")"; |
| + } else { |
| + outputBus = |
| + AudioBus::create(setup.numberOfChannels, action.numberOfFrames); |
| + fifo->pull(outputBus.get(), action.numberOfFrames); |
| + LOG(INFO) << "PULL " << action.numberOfFrames << " frames"; |
| + } |
| + } |
| + |
| + // Get FIFO config data. |
| + const PushPullFIFOStateForTest actualState = fifo->getStateForTest(); |
| + |
| + // Verify the read/write indexes. |
| + EXPECT_EQ(actualState.indexRead, expectedState.indexRead); |
| + EXPECT_EQ(actualState.indexWrite, expectedState.indexWrite); |
| + EXPECT_EQ(actualState.overflowCount, expectedState.overflowCount); |
| + EXPECT_EQ(actualState.underflowCount, expectedState.underflowCount); |
| + |
| + // Verify in-FIFO samples. |
| + for (const auto& sample : expectedState.fifoSamples) { |
| + EXPECT_TRUE(verifyBusValueAtIndex(fifo->bus(), sample.index, sample.value)); |
| + } |
| + |
| + // Verify samples from the most recent output bus. |
| + for (const auto& sample : expectedState.outputSamples) { |
| + EXPECT_TRUE( |
| + verifyBusValueAtIndex(outputBus.get(), sample.index, sample.value)); |
| + } |
| +} |
| + |
| +INSTANTIATE_TEST_CASE_P(PushPullFIFOTest, |
| + PushPullFIFOTest, |
| + ::testing::ValuesIn(basicFIFOTestParams)); |
| + |
| +// TODO(hongchan): Do death tests for SECURITY_CHECK(). |
| + |
| +} // namespace |
| + |
| +} // namespace blink |