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..3657aeae7c457110db9ab5eda21b42c67df16036 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp |
| @@ -0,0 +1,162 @@ |
| +// Copyright 2016 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/testing/TestingPlatformSupport.h" |
| +#include "testing/gtest/include/gtest/gtest-death-test.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "wtf/PtrUtil.h" |
| +#include <memory> |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +const unsigned kNumberOfChannel = 2; |
| +const size_t kFIFOSize = 8192; |
| +const size_t kCallbackBufferSize = 1024; |
|
Raymond Toy
2017/01/12 19:29:40
If you have to pick values for this, why not use "
o1ka
2017/01/13 11:23:44
I believe we need to have parametrized tests (TEST
hongchan
2017/01/13 23:29:23
Please bear with me - this is my first attempt to
hongchan
2017/01/13 23:29:23
Done.
|
| +const size_t kRenderQuantum = 128; |
|
o1ka
2017/01/13 11:23:44
The values are multipliers of each other, so many
|
| + |
| +// Fills AudioBus with a value. |
| +void fillBusWithValue(AudioBus* targetBus, float value) { |
| + for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { |
| + float* busChannel = targetBus->channel(c)->mutableData(); |
| + std::fill(busChannel, busChannel + targetBus->channel(c)->length(), value); |
| + } |
| +} |
| + |
| +// Check if AudioBus is filled with a specific value within the given range. |
|
o1ka
2017/01/13 11:23:44
To make sure the indexes are always consistent and
hongchan
2017/01/13 23:29:23
Done.
|
| +bool isBusConstantValueOf(AudioBus* targetBus, |
| + float value, |
| + unsigned startFrame, |
| + unsigned endFrame) { |
| + for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { |
| + const float* busChannel = targetBus->channel(c)->data(); |
| + for (unsigned i = startFrame; i < endFrame; ++i) { |
| + if (busChannel[i] != value) |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| +TEST(PushPullFIFOTest, Construction) { |
| + std::unique_ptr<PushPullFIFO> fifo = |
| + WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kFIFOSize)); |
| + |
| + EXPECT_EQ(static_cast<int>(kFIFOSize), fifo->length()); |
| + EXPECT_EQ(0, fifo->framesAvailable()); |
| + EXPECT_EQ(kNumberOfChannel, fifo->numberOfChannels()); |
| +} |
| + |
| +TEST(PushPullFIFOTest, BasicOperation) { |
| + // Create a FIFO of 2X render quantum. (256 frames) |
| + std::unique_ptr<PushPullFIFO> fifo = |
| + WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, 2 * kRenderQuantum)); |
| + |
| + RefPtr<AudioBus> inputBus = |
| + AudioBus::create(kNumberOfChannel, kRenderQuantum); |
| + RefPtr<AudioBus> outputBus = |
| + AudioBus::create(kNumberOfChannel, 2 * kRenderQuantum); |
| + |
| + // Create an input vector (128 frames) of '1'. |
| + fillBusWithValue(inputBus.get(), 1); |
| + EXPECT_TRUE(isBusConstantValueOf(inputBus.get(), 1, 0, kRenderQuantum)); |
| + |
| + // Push and pull by 128 frames. |
| + fifo->push(inputBus.get()); |
| + fifo->pull(outputBus.get(), kRenderQuantum); |
| + |
| + // Thus no frames available in FIFO. |
| + EXPECT_EQ(fifo->framesAvailable(), 0); |
| + |
| + // The half of output bus should be the exact copy of input bus. The rest |
| + // should be 0. |
| + EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), 1, 0, kRenderQuantum)); |
| + EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), 0, kRenderQuantum, |
| + 2 * kRenderQuantum)); |
| +} |
| + |
| +TEST(PushPullFIFOTest, WrapAround) { |
| + std::unique_ptr<PushPullFIFO> fifo = |
| + WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kCallbackBufferSize)); |
| + |
| + RefPtr<AudioBus> inputBus = |
| + AudioBus::create(kNumberOfChannel, kRenderQuantum); |
| + RefPtr<AudioBus> outputBus = |
| + AudioBus::create(kNumberOfChannel, kCallbackBufferSize); |
| + |
| + unsigned numberOfblocks = kCallbackBufferSize / kRenderQuantum; |
| + |
| + // The first round fills the FIFO with 1. |
| + fillBusWithValue(inputBus.get(), 1); |
| + for (unsigned i = 0; i < numberOfblocks; ++i) |
| + fifo->push(inputBus.get()); |
| + |
| + // Then pull the half of FIFO. |
| + for (unsigned i = 0; i < 0.5 * numberOfblocks; ++i) |
| + fifo->pull(outputBus.get(), kRenderQuantum); |
| + |
| + // Fill the emptied half with 2. After this point the FIFO content should |
| + // be { 2, 2, 2, 2, 1, 1, 1, 1 } by each 128 frame block. Note that the read |
| + // index is in the middle. |
| + fillBusWithValue(inputBus.get(), 2); |
| + for (unsigned i = 0; i < 0.5 * numberOfblocks; ++i) |
| + fifo->push(inputBus.get()); |
| + |
| + // If FIFO is pulled 8 times (numberOfBlocks), it must produce the following |
| + // block sequence because of warp-around. |
| + float expectedValueInBlocks[] = {1, 1, 1, 1, 2, 2, 2, 2}; |
| + |
| + for (unsigned i = 0; i < numberOfblocks; ++i) { |
| + fifo->pull(outputBus.get(), kRenderQuantum); |
| + EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), expectedValueInBlocks[i], |
| + 0, kRenderQuantum)); |
| + } |
| +} |
| + |
| +TEST(PushPullFIFOTest, Overflow) { |
| + std::unique_ptr<PushPullFIFO> fifo = |
| + WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kCallbackBufferSize)); |
| + RefPtr<AudioBus> inputBus = |
| + AudioBus::create(kNumberOfChannel, kRenderQuantum); |
| + |
| + unsigned numberOfblocks = kCallbackBufferSize / kRenderQuantum; |
| + |
| + // Push data up to the full capacity of FIFO. |
| + fillBusWithValue(inputBus.get(), 1); |
| + for (unsigned i = 0; i < numberOfblocks; ++i) |
| + fifo->push(inputBus.get()); |
| + |
| + // Pushing one more time without pulling causes DCHECK failure. |
| + EXPECT_DEBUG_DEATH(fifo->push(inputBus.get()), "fifoOverflow"); |
|
o1ka
2017/01/13 11:23:44
But this should not be the case in real life, righ
hongchan
2017/01/13 23:29:23
Without DCHECK, how can the test runner detect suc
|
| +} |
| + |
| +TEST(PushPullFIFOTest, Underflow) { |
| + std::unique_ptr<PushPullFIFO> fifo = |
| + WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kCallbackBufferSize)); |
| + RefPtr<AudioBus> inputBus = |
| + AudioBus::create(kNumberOfChannel, kRenderQuantum); |
| + RefPtr<AudioBus> outputBus = |
| + AudioBus::create(kNumberOfChannel, kRenderQuantum); |
| + |
| + unsigned numberOfblocks = kCallbackBufferSize / kRenderQuantum; |
| + |
| + fillBusWithValue(inputBus.get(), 1); |
| + for (unsigned i = 0; i < numberOfblocks; ++i) |
| + fifo->push(inputBus.get()); |
| + |
| + // Then pull the entire FIFO content. The FIFO will be empty. |
| + for (unsigned i = 0; i < numberOfblocks; ++i) |
| + fifo->pull(outputBus.get(), kRenderQuantum); |
| + |
| + // Pulling an empty FIFO results the silence. |
| + fifo->pull(outputBus.get(), kRenderQuantum); |
| + EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), 0, 0, kRenderQuantum)); |
| +} |
| + |
| +} // namespace blink |