| // Copyright 2025 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 "quiche/quic/moqt/moqt_outstanding_objects.h" | |
| #include <cstdint> | |
| #include "quiche/quic/moqt/moqt_messages.h" | |
| #include "quiche/common/platform/api/quiche_test.h" | |
| namespace moqt::test { | |
| namespace { | |
| class MoqtOutstandingObjectsTest : public quiche::test::QuicheTest {}; | |
| constexpr uint64_t kDefaultMaxOutOfOrderObjects = 10; | |
| TEST_F(MoqtOutstandingObjectsTest, AckMissingObject) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| EXPECT_EQ(objects.tracked_objects_count(), 0); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 6)), -1); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, AckFutureObject) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| objects.OnObjectAdded(Location(5, 5)); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 4)), -1); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 6)), -1); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, AckOneObject) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| objects.OnObjectAdded(Location(5, 6)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 1); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 6)), 0); | |
| EXPECT_EQ(objects.tracked_objects_count(), 0); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, AckTwoObjectsInOrder) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| objects.OnObjectAdded(Location(5, 6)); | |
| objects.OnObjectAdded(Location(5, 7)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 2); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 6)), 0); | |
| EXPECT_EQ(objects.tracked_objects_count(), 1); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 7)), 0); | |
| EXPECT_EQ(objects.tracked_objects_count(), 0); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, AckTwoObjectsOutOfOrder) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| objects.OnObjectAdded(Location(5, 6)); | |
| objects.OnObjectAdded(Location(5, 7)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 2); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 7)), 1); | |
| EXPECT_EQ(objects.tracked_objects_count(), 2); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 6)), 0); | |
| EXPECT_EQ(objects.tracked_objects_count(), 0); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, AddTwoObjectsOutOfOrder) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| objects.OnObjectAdded(Location(10, 0)); | |
| objects.OnObjectAdded(Location(5, 0)); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(10, 0)), 0); | |
| EXPECT_EQ(objects.tracked_objects_count(), 1); | |
| EXPECT_EQ(objects.OnObjectAcked(Location(5, 0)), 0); | |
| EXPECT_EQ(objects.tracked_objects_count(), 0); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, | |
| RemoveObjectsWhenOutOfOrderThresholdExceeded) { | |
| MoqtOutstandingObjects objects(3); | |
| for (int i = 0; i < 10; ++i) { | |
| objects.OnObjectAdded(Location(i, 0)); | |
| } | |
| EXPECT_EQ(objects.tracked_objects_count(), 10); | |
| objects.OnObjectAcked(Location(1, 0)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 10); | |
| objects.OnObjectAcked(Location(2, 0)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 10); | |
| objects.OnObjectAcked(Location(3, 0)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 10); | |
| objects.OnObjectAcked(Location(4, 0)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 5); | |
| EXPECT_EQ(-1, objects.OnObjectAcked(Location(0, 0))); | |
| EXPECT_EQ(0, objects.OnObjectAcked(Location(5, 0))); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, | |
| RemoveObjectsWhenOutOfOrderThresholdExceeded2) { | |
| MoqtOutstandingObjects objects(3); | |
| for (int i = 0; i < 10; ++i) { | |
| objects.OnObjectAdded(Location(i, 0)); | |
| } | |
| EXPECT_EQ(objects.tracked_objects_count(), 10); | |
| objects.OnObjectAcked(Location(5, 0)); | |
| EXPECT_EQ(objects.tracked_objects_count(), 8); | |
| EXPECT_EQ(-1, objects.OnObjectAcked(Location(0, 0))); | |
| EXPECT_EQ(-1, objects.OnObjectAcked(Location(1, 0))); | |
| EXPECT_EQ(0, objects.OnObjectAcked(Location(2, 0))); | |
| } | |
| TEST_F(MoqtOutstandingObjectsTest, ObjectsRemovedWhenLimitExceeded) { | |
| MoqtOutstandingObjects objects(kDefaultMaxOutOfOrderObjects); | |
| for (int i = 0; i < MoqtOutstandingObjects::kMaxObjectsTracked; ++i) { | |
| objects.OnObjectAdded(Location(i, 0)); | |
| } | |
| EXPECT_EQ(objects.tracked_objects_count(), | |
| MoqtOutstandingObjects::kMaxObjectsTracked); | |
| objects.OnObjectAdded(Location(10000, 0)); | |
| EXPECT_EQ(objects.tracked_objects_count(), | |
| MoqtOutstandingObjects::kMaxObjectsTracked); | |
| EXPECT_EQ(-1, objects.OnObjectAcked(Location(0, 0))); | |
| EXPECT_EQ(0, objects.OnObjectAcked(Location(1, 0))); | |
| } | |
| } // namespace | |
| } // namespace moqt::test |