Delete SimulatedBuffer
This class is unused.
Test: launch_cvd
Bug: 148312842
Change-Id: If25fbc77ad5f8f9c8565e398fe7c22b22a6fa583
diff --git a/common/libs/utils/Android.bp b/common/libs/utils/Android.bp
index 7330315..268862f 100644
--- a/common/libs/utils/Android.bp
+++ b/common/libs/utils/Android.bp
@@ -41,12 +41,3 @@
},
defaults: ["cuttlefish_host_and_guest"],
}
-
-cc_test {
- name: "cuttlefish_simulated_buffer_test",
- srcs: ["simulated_buffer_test.cpp"],
- shared_libs: ["libcuttlefish_utils"],
- gtest: true,
- defaults: ["cuttlefish_host_only"],
- test_suites: ["general-tests"],
-}
diff --git a/common/libs/utils/TEST_MAPPING b/common/libs/utils/TEST_MAPPING
deleted file mode 100644
index 61de458..0000000
--- a/common/libs/utils/TEST_MAPPING
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "presubmit": [
- {
- "name": "cuttlefish_simulated_buffer_test",
- "host": true
- }
- ]
-}
diff --git a/common/libs/utils/simulated_buffer.h b/common/libs/utils/simulated_buffer.h
deleted file mode 100644
index a61108d..0000000
--- a/common/libs/utils/simulated_buffer.h
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <stdint.h>
-#include <unistd.h>
-#include <time.h>
-
-#include "common/libs/time/monotonic_time.h"
-
-/**
- * This abstract class simulates a buffer that either fills or empties at
- * a specified rate.
- *
- * The simulated buffer automatically fills or empties at a specific rate.
- *
- * An item is the thing contained in the simulated buffer. Items are moved
- * in and out of the buffer without subdivision.
- *
- * An integral number of items must arrive / depart in each second.
- * This number is stored in items_per_second_
- *
- * items_per_second * 2000000000 must fit within an int64_t. This
- * works if items_per_second is represented by an int32.
- *
- * The base class does have the concept of capacity, but doesn't use it.
- * It is included here to simplify unit testing.
- *
- * For actual use, see SimulatedInputBuffer and SimulatedOutputBuffer below.
- */
-class SimulatedBufferBase {
- public:
- static inline int64_t divide_and_round_up(int64_t q, int64_t d) {
- return q / d + ((q % d) != 0);
- }
-
- SimulatedBufferBase(
- int32_t items_per_second,
- int64_t simulated_item_capacity,
- cvd::time::MonotonicTimePointFactory* clock =
- cvd::time::MonotonicTimePointFactory::GetInstance()) :
- clock_(clock),
- current_item_num_(0),
- base_item_num_(0),
- simulated_item_capacity_(simulated_item_capacity),
- items_per_second_(items_per_second),
- initialize_(true),
- paused_(false) { }
-
- virtual ~SimulatedBufferBase() { }
-
- int64_t GetCurrentItemNum() {
- Update();
- return current_item_num_;
- }
-
- const cvd::time::MonotonicTimePoint GetLastUpdatedTime() const {
- return current_time_;
- }
-
- // Sleep for the given amount of time. Subclasses may override this to use
- // different sleep calls.
- // Sleep is best-effort. The code assumes that the acutal sleep time may be
- // greater or less than the time requested.
- virtual void SleepUntilTime(const cvd::time::MonotonicTimePoint& in) {
- struct timespec ts;
- in.ToTimespec(&ts);
- clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL);
- }
-
- // The time counter may not start at 0. Concrete classes should call this
- // to allow the buffer simulation to read the current time number and
- // initialize its internal state.
- virtual void Init() {
- if (initialize_) {
- clock_->FetchCurrentTime(&base_time_);
- current_time_ = base_time_;
- initialize_ = false;
- }
- }
-
- virtual void Update() {
- if (initialize_) {
- Init();
- }
- cvd::time::MonotonicTimePoint now;
- clock_->FetchCurrentTime(&now);
- // We can't call FetchCurrentTime() in the constuctor because a subclass may
- // want to override it, so we initialze the times to 0. If we detect this
- // case go ahead and initialize to a current timestamp.
- if (paused_) {
- base_time_ += now - current_time_;
- current_time_ = now;
- return;
- }
- // Avoid potential overflow by limiting the scaling to one time second.
- // There is no round-off error here because the bases are adjusted for full
- // seconds.
- // There is no issue with int64 overflow because 2's compliment subtraction
- // is immune to overflow.
- // However, this does assume that kNanosecondsPerSecond * items_per_second_
- // fits in an int64.
- cvd::time::Seconds seconds(now - base_time_);
- base_time_ += seconds;
- base_item_num_ += seconds.count() * items_per_second_;
- current_time_ = now;
- current_item_num_ =
- cvd::time::Nanoseconds(now - base_time_).count() *
- items_per_second_ / cvd::time::kNanosecondsPerSecond +
- base_item_num_;
- }
-
- // If set to true new items will not be created.
- bool SetPaused(bool new_state) {
- bool rval = paused_;
- Update();
- paused_ = new_state;
- return rval;
- }
-
- // Calculate the TimePoint that corresponds to an item.
- // Caution: This may not return a correct time for items in the past.
- cvd::time::MonotonicTimePoint CalculateItemTime(int64_t item) {
- int64_t seconds = (item - base_item_num_) / items_per_second_;
- int64_t new_base_item_num = base_item_num_ + seconds * items_per_second_;
- return base_time_ + cvd::time::Seconds(seconds) +
- cvd::time::Nanoseconds(divide_and_round_up(
- (item - new_base_item_num) *
- cvd::time::kNanosecondsPerSecond,
- items_per_second_));
- }
-
- // Sleep until the given item number is generated. If the generator is
- // paused unpause it to make the sleep finite.
- void SleepUntilItem(int64_t item) {
- if (paused_) {
- SetPaused(false);
- }
- cvd::time::MonotonicTimePoint desired_time =
- CalculateItemTime(item);
- while (1) {
- Update();
- if (current_item_num_ - item >= 0) {
- return;
- }
- SleepUntilTime(desired_time);
- }
- }
-
- protected:
- // Source of the timepoints.
- cvd::time::MonotonicTimePointFactory* clock_;
- // Time when the other values in the structure were updated.
- cvd::time::MonotonicTimePoint current_time_;
- // Most recent time when there was no round-off error between the clock and
- // items.
- cvd::time::MonotonicTimePoint base_time_;
- // Number of the current item.
- int64_t current_item_num_;
- // Most recent item number where there was no round-off error between the
- // clock and items.
- int64_t base_item_num_;
- // Simulated_Item_Capacity of the buffer in items.
- int64_t simulated_item_capacity_;
- // Number of items that are created in 1s. A typical number would be 48000.
- int32_t items_per_second_;
- bool initialize_;
- // If true then don't generate new items.
- bool paused_;
-};
-
-/**
- * This is a simulation of an output buffer that drains at a constant rate.
- */
-class SimulatedOutputBuffer : public SimulatedBufferBase {
- public:
- SimulatedOutputBuffer(
- int64_t item_rate,
- int64_t simulated_item_capacity,
- cvd::time::MonotonicTimePointFactory* clock =
- cvd::time::MonotonicTimePointFactory::GetInstance()) :
- SimulatedBufferBase(item_rate, simulated_item_capacity, clock) {
- output_buffer_item_num_ = current_item_num_;
- }
-
- void Update() override {
- SimulatedBufferBase::Update();
- if ((output_buffer_item_num_ - current_item_num_) < 0) {
- // We ran out of items at some point in the past. However, the
- // output capactiy can't be negative.
- output_buffer_item_num_ = current_item_num_;
- }
- }
-
- int64_t AddToOutputBuffer(int64_t num_new_items, bool block) {
- Update();
- // The easy case: num_new_items fit in the bucket.
- if ((output_buffer_item_num_ + num_new_items - current_item_num_) <=
- simulated_item_capacity_) {
- output_buffer_item_num_ += num_new_items;
- return num_new_items;
- }
- // If we're non-blocking accept enough items to fill the output.
- if (!block) {
- int64_t used = current_item_num_ + simulated_item_capacity_ -
- output_buffer_item_num_;
- output_buffer_item_num_ = current_item_num_ + simulated_item_capacity_;
- return used;
- }
- int64_t new_output_buffer_item_num = output_buffer_item_num_ + num_new_items;
- SleepUntilItem(new_output_buffer_item_num - simulated_item_capacity_);
- output_buffer_item_num_ = new_output_buffer_item_num;
- return num_new_items;
- }
-
- int64_t GetNextOutputBufferItemNum() {
- Update();
- return output_buffer_item_num_;
- }
-
- cvd::time::MonotonicTimePoint GetNextOutputBufferItemTime() {
- Update();
- return CalculateItemTime(output_buffer_item_num_);
- }
-
- int64_t GetOutputBufferSize() {
- Update();
- return output_buffer_item_num_ - current_item_num_;
- }
-
- void Drain() {
- SleepUntilItem(output_buffer_item_num_);
- }
-
- protected:
- int64_t output_buffer_item_num_;
-};
-
-/**
- * Simulates an input buffer that fills at a constant rate.
- */
-class SimulatedInputBuffer : public SimulatedBufferBase {
- public:
- SimulatedInputBuffer(
- int64_t item_rate,
- int64_t simulated_item_capacity,
- cvd::time::MonotonicTimePointFactory* clock =
- cvd::time::MonotonicTimePointFactory::GetInstance()) :
- SimulatedBufferBase(item_rate, simulated_item_capacity, clock) {
- input_buffer_item_num_ = current_item_num_;
- lost_input_items_ = 0;
- }
-
- void Update() override {
- SimulatedBufferBase::Update();
- if ((current_item_num_ - input_buffer_item_num_) >
- simulated_item_capacity_) {
- // The buffer overflowed at some point in the past. Account for the lost
- // times.
- int64_t new_input_buffer_item_num =
- current_item_num_ - simulated_item_capacity_;
- lost_input_items_ +=
- new_input_buffer_item_num - input_buffer_item_num_;
- input_buffer_item_num_ = new_input_buffer_item_num;
- }
- }
-
- int64_t RemoveFromInputBuffer(int64_t num_items_wanted, bool block) {
- Update();
- if (!block) {
- int64_t num_items_available = current_item_num_ - input_buffer_item_num_;
- if (num_items_available < num_items_wanted) {
- input_buffer_item_num_ += num_items_available;
- return num_items_available;
- } else {
- input_buffer_item_num_ += num_items_wanted;
- return num_items_wanted;
- }
- }
- // Calculate the item number that is being claimed. Sleep until it appears.
- // Advancing input_buffer_item_num_ causes a negative value to be compared
- // to the capacity, effectively disabling the overflow detection code
- // in Update().
- input_buffer_item_num_ += num_items_wanted;
- while (input_buffer_item_num_ - current_item_num_ > 0) {
- SleepUntilItem(input_buffer_item_num_);
- }
- return num_items_wanted;
- }
-
- int64_t GetLostInputItems() {
- Update();
- int64_t rval = lost_input_items_;
- lost_input_items_ = 0;
- return rval;
- }
-
- protected:
- int64_t input_buffer_item_num_;
- int64_t lost_input_items_;
-};
diff --git a/common/libs/utils/simulated_buffer_test.cpp b/common/libs/utils/simulated_buffer_test.cpp
deleted file mode 100644
index c3fbe49..0000000
--- a/common/libs/utils/simulated_buffer_test.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "common/libs/utils/simulated_buffer.h"
-#include <gtest/gtest.h>
-
-using cvd::time::MonotonicTimePoint;
-using cvd::time::MonotonicTimePointFactory;
-using cvd::time::Seconds;
-using cvd::time::Milliseconds;
-using cvd::time::Nanoseconds;
-using cvd::time::kNanosecondsPerSecond;
-
-class MockTimepointFactory : public MonotonicTimePointFactory {
- public:
- virtual void FetchCurrentTime(MonotonicTimePoint* dest) const override {
- *dest = system_time_;
- }
-
- void SetTime(const MonotonicTimePoint& in) {
- system_time_ = in;
- }
-
- protected:
- MonotonicTimePoint system_time_;
-};
-
-template <typename T> class MockSimulatedBuffer : public T {
- public:
- MockSimulatedBuffer(
- int64_t sample_rate,
- int64_t capacity,
- MockTimepointFactory* factory) :
- T(sample_rate, capacity, factory),
- factory_(factory) { }
-
- void FetchCurrentTime(MonotonicTimePoint* dest) const {
- return factory_->FetchCurrentTime(dest);
- }
-
- void SleepUntilTime(const MonotonicTimePoint& tick) {
- factory_->SetTime(tick);
- }
-
- protected:
- // Save a redundant pointer to avoid downcasting
- MockTimepointFactory* factory_;
-};
-
-static const int64_t kItemRate = 48000;
-static const int64_t kBufferCapacity = 4800;
-
-class SimulatedBufferTest : public ::testing::Test {
- public:
- MockTimepointFactory clock;
- MockSimulatedBuffer<SimulatedBufferBase> buffer;
-
- SimulatedBufferTest() : buffer(kItemRate, kBufferCapacity, &clock) { }
-};
-
-TEST_F(SimulatedBufferTest, TimeMocking) {
- // Ensure that the mocked clock starts at the epoch.
- MonotonicTimePoint epoch_time;
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(epoch_time, actual_time);
-
- // Ensure that sleeping works
- MonotonicTimePoint test_time = actual_time + Seconds(10);
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
-
- // Try one more sleep to make sure that time moves forward
- test_time += Seconds(5);
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
-}
-
-TEST_F(SimulatedBufferTest, ItemScaling) {
- // Make certain that we start at item 0
- EXPECT_EQ(0, buffer.GetCurrentItemNum());
-
- // Make certain that the expected number of items appear in 1 second
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- MonotonicTimePoint test_time = actual_time + Seconds(1);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(kItemRate, buffer.GetCurrentItemNum());
-
- // Sleep an additional 10 seconds to make certain that the item numbers
- // increment
- test_time += Seconds(10);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(11 * kItemRate, buffer.GetCurrentItemNum());
-
- // Make certain that partial seconds work
- test_time += Milliseconds(1500);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(12.5 * kItemRate, buffer.GetCurrentItemNum());
-
- // Make certain that we don't get new items when paused
- buffer.SetPaused(true);
- test_time += Seconds(10);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(12.5 * kItemRate, buffer.GetCurrentItemNum());
-
- // Make certain that we start getting items when pausing stops
- buffer.SetPaused(false);
- test_time += Milliseconds(500);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(13 * kItemRate, buffer.GetCurrentItemNum());
-}
-
-TEST_F(SimulatedBufferTest, ItemSleeping) {
- // See if sleeping on an time causes the right amount of time to pass
- EXPECT_EQ(0, buffer.GetCurrentItemNum());
- MonotonicTimePoint base_time;
- buffer.FetchCurrentTime(&base_time);
-
- // Wait for 1500ms worth of samples
- buffer.SleepUntilItem(kItemRate * 1500 / 1000);
- EXPECT_EQ(kItemRate * 1500 / 1000, buffer.GetCurrentItemNum());
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(1500, Milliseconds(actual_time - base_time).count());
-
- // Now wait again for more samples
- buffer.SleepUntilItem(kItemRate * 2500 / 1000);
- EXPECT_EQ(kItemRate * 2500 / 1000, buffer.GetCurrentItemNum());
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(2500, Milliseconds(actual_time - base_time).count());
-}
-
-class OutputBufferTest : public ::testing::Test {
- public:
- MockTimepointFactory clock;
- MockSimulatedBuffer<SimulatedOutputBuffer> buffer;
-
- OutputBufferTest() : buffer(kItemRate, kBufferCapacity, &clock) { }
-};
-
-TEST_F(OutputBufferTest, NonBlockingQueueing) {
- int64_t half_buffer = kBufferCapacity / 2;
- EXPECT_EQ(0, buffer.GetCurrentItemNum());
-
- // Filling half of the buffer should not block
- MonotonicTimePoint test_time;
- buffer.FetchCurrentTime(&test_time);
- EXPECT_EQ(half_buffer, buffer.AddToOutputBuffer(half_buffer, false));
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(half_buffer, buffer.GetOutputBufferSize());
-
- // Filling all but one entry of the buffer should not block
- EXPECT_EQ(half_buffer - 1,
- buffer.AddToOutputBuffer(half_buffer - 1, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity - 1, buffer.GetOutputBufferSize());
-
- // Filling the entire buffer should not block
- EXPECT_EQ(1, buffer.AddToOutputBuffer(half_buffer, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(actual_time, test_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // The buffer should reject additional data but not block
- EXPECT_EQ(0, buffer.AddToOutputBuffer(half_buffer, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // One quarter of the buffer should drain in the expected time
- Nanoseconds quarter_drain_time(
- kBufferCapacity / 4 * kNanosecondsPerSecond / kItemRate);
- test_time += quarter_drain_time;
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(actual_time, test_time);
- EXPECT_EQ(kBufferCapacity * 3 / 4, buffer.GetOutputBufferSize());
-
- // The buffer should now accept new data without blocking
- EXPECT_EQ(kBufferCapacity / 4,
- buffer.AddToOutputBuffer(half_buffer, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // Now that the buffer is full it should reject additional data but
- // not block
- EXPECT_EQ(0, buffer.AddToOutputBuffer(half_buffer, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // Wait for 3/4 of the buffer to drain
- test_time += Nanoseconds(3 * quarter_drain_time.count());
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity / 4, buffer.GetOutputBufferSize());
-
- // The entire buffer should drain on schedule
- test_time += Nanoseconds(quarter_drain_time.count() - 1);
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(1, buffer.GetOutputBufferSize());
- test_time += Nanoseconds(1);
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetOutputBufferSize());
-
- // It should be possible to fill the buffer in a single shot
- EXPECT_EQ(kBufferCapacity,
- buffer.AddToOutputBuffer(kBufferCapacity, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // The buffer shouldn't accept additional data but shouldn't block
- EXPECT_EQ(0, buffer.AddToOutputBuffer(1, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // The buffer should underflow sanely
- test_time += Nanoseconds(6 * quarter_drain_time.count());
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetOutputBufferSize());
-
- // The underflow shouldn't increase the buffer's capacity
- EXPECT_EQ(kBufferCapacity,
- buffer.AddToOutputBuffer(kBufferCapacity + 1, false));
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
-}
-
-TEST_F(OutputBufferTest, BlockingQueueing) {
- int64_t half_buffer = kBufferCapacity / 2;
-
- // Check the initial setup
- EXPECT_EQ(0, buffer.GetCurrentItemNum());
- MonotonicTimePoint test_time;
- buffer.FetchCurrentTime(&test_time);
-
- // Filling half the buffer works without blocking
- EXPECT_EQ(half_buffer, buffer.AddToOutputBuffer(half_buffer, true));
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(half_buffer, buffer.GetOutputBufferSize());
-
- // Filling all but one entry of the buffer also works without blocking
- EXPECT_EQ(half_buffer - 1,
- buffer.AddToOutputBuffer(half_buffer - 1, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity - 1, buffer.GetOutputBufferSize());
-
- // Putting the last sample into the buffer doesn't block
- EXPECT_EQ(1, buffer.AddToOutputBuffer(1, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // Putting more data into the buffer causes blocking
- EXPECT_EQ(half_buffer, buffer.AddToOutputBuffer(half_buffer, true));
- Nanoseconds half_drain_time(
- ((kBufferCapacity / 2) * kNanosecondsPerSecond + kItemRate - 1) /
- kItemRate);
- Nanoseconds quarter_drain_time(half_drain_time.count() / 2);
- test_time += half_drain_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // The buffer drains as expected
- test_time += quarter_drain_time;
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity * 3 / 4, buffer.GetOutputBufferSize());
-
- // Overfilling the drained buffer also causes blocking
- EXPECT_EQ(half_buffer, buffer.AddToOutputBuffer(half_buffer, true));
- test_time += quarter_drain_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // The buffer drains on schedule
- test_time += Nanoseconds(half_drain_time.count() * 2 - 1);
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(1, buffer.GetOutputBufferSize());
- test_time += Nanoseconds(1);
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetOutputBufferSize());
-
- // It's possible to fill the entire output buffer in 1 shot without blocking
- EXPECT_EQ(kBufferCapacity,
- buffer.AddToOutputBuffer(kBufferCapacity, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-
- // Adding a single extra sample causes some blocking
- EXPECT_EQ(1, buffer.AddToOutputBuffer(1, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_LT(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity, buffer.GetOutputBufferSize());
-}
-
-class InputBufferTest : public ::testing::Test {
- public:
- MockTimepointFactory clock;
- MockSimulatedBuffer<SimulatedInputBuffer> buffer;
-
- InputBufferTest() : buffer(kItemRate, kBufferCapacity, &clock) { }
-};
-
-TEST_F(InputBufferTest, NonBlockingInput) {
- Nanoseconds quarter_fill_time(kBufferCapacity / 4 * kNanosecondsPerSecond /
- kItemRate);
- // Verify that the buffer starts empty
- EXPECT_EQ(0, buffer.GetCurrentItemNum());
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(0, buffer.RemoveFromInputBuffer(kBufferCapacity, false));
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- // Wait for 1/4 of the buffer to fill
- MonotonicTimePoint test_time = actual_time + quarter_fill_time;
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- // Verify that we can read the samples in two groups
- EXPECT_EQ(kBufferCapacity / 8,
- buffer.RemoveFromInputBuffer(kBufferCapacity / 8, false));
- EXPECT_EQ(kBufferCapacity / 8,
- buffer.RemoveFromInputBuffer(kBufferCapacity, false));
-
- // Verify that there are no samples left and that we did not block
- EXPECT_EQ(0, buffer.RemoveFromInputBuffer(kBufferCapacity, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
-
- // Verify that the buffer fills on schedule
- test_time += Nanoseconds(4 * quarter_fill_time.count() - 1);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(kBufferCapacity - 1,
- buffer.RemoveFromInputBuffer(kBufferCapacity, false));
- test_time += Nanoseconds(1);
- buffer.SleepUntilTime(test_time);
- EXPECT_EQ(1, buffer.RemoveFromInputBuffer(kBufferCapacity, false));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- // Verify that the buffer overflows as expected
- test_time += Nanoseconds(5 * quarter_fill_time.count());
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity / 4, buffer.GetLostInputItems());
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- EXPECT_EQ(kBufferCapacity,
- buffer.RemoveFromInputBuffer(2 * kBufferCapacity, false));
- EXPECT_EQ(0, buffer.RemoveFromInputBuffer(kBufferCapacity, false));
-}
-
-TEST_F(InputBufferTest, BlockingInput) {
- Nanoseconds quarter_fill_time(kBufferCapacity / 4 * kNanosecondsPerSecond /
- kItemRate);
- // Verify that the buffer starts empty
- EXPECT_EQ(0, buffer.GetCurrentItemNum());
- MonotonicTimePoint actual_time;
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- // Wait for 1/4 of the buffer to fill
- MonotonicTimePoint test_time = actual_time + quarter_fill_time;
- EXPECT_EQ(kBufferCapacity / 4,
- buffer.RemoveFromInputBuffer(kBufferCapacity / 4, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- // Verify that the buffer fills on schedule
- test_time += Nanoseconds(4 * quarter_fill_time.count());
- EXPECT_EQ(kBufferCapacity,
- buffer.RemoveFromInputBuffer(kBufferCapacity, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(0, buffer.GetLostInputItems());
-
- // Verify that the buffer overflows as expected
- test_time += Nanoseconds(5 * quarter_fill_time.count());
- buffer.SleepUntilTime(test_time);
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
- EXPECT_EQ(kBufferCapacity / 4, buffer.GetLostInputItems());
- EXPECT_EQ(0, buffer.GetLostInputItems());
- EXPECT_EQ(kBufferCapacity,
- buffer.RemoveFromInputBuffer(kBufferCapacity, true));
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
-
- // Verify that reads bigger than the buffer work as expected
- test_time += Nanoseconds(8 * quarter_fill_time.count());
- EXPECT_EQ(kBufferCapacity * 2,
- buffer.RemoveFromInputBuffer(kBufferCapacity * 2, true));
- EXPECT_EQ(0, buffer.GetLostInputItems());
- buffer.FetchCurrentTime(&actual_time);
- EXPECT_EQ(test_time, actual_time);
-}