@@ -2176,4 +2176,103 @@ TEST_F(MoQRelayTest, ExactNamespaceSubscriberReceivesPublishNamespace) {
21762176 removeSession (subscriber);
21772177}
21782178
2179+ // Test: TrackStatus on non-existent track
2180+ TEST_F (MoQRelayTest, TrackStatusNonExistentTrack) {
2181+ auto clientSession = createMockSession ();
2182+
2183+ // Request trackStatus for a track that doesn't exist
2184+ TrackStatus trackStatus;
2185+ trackStatus.fullTrackName = kTestTrackName ;
2186+ trackStatus.requestID = RequestID (1 );
2187+
2188+ withSessionContext (clientSession, [&]() {
2189+ auto task = relay_->trackStatus (trackStatus);
2190+ auto res = folly::coro::blockingWait (std::move (task), exec_.get ());
2191+
2192+ // Should return error indicating track not found
2193+ EXPECT_FALSE (res.hasValue ());
2194+ EXPECT_EQ (res.error ().errorCode , TrackStatusErrorCode::TRACK_NOT_EXIST );
2195+ EXPECT_FALSE (res.error ().reasonPhrase .empty ());
2196+ });
2197+
2198+ removeSession (clientSession);
2199+ }
2200+
2201+ // Test: TrackStatus on existing track - returns forwarder state (no upstream
2202+ // call)
2203+ TEST_F (MoQRelayTest, TrackStatusSuccessfulForward) {
2204+ auto publisherSession = createMockSession ();
2205+ auto clientSession = createMockSession ();
2206+
2207+ doPublish (publisherSession, kTestTrackName );
2208+
2209+ auto consumer = createMockConsumer ();
2210+ subscribeToTrack (clientSession, kTestTrackName , consumer, RequestID (1 ));
2211+
2212+ TrackStatus trackStatus;
2213+ trackStatus.fullTrackName = kTestTrackName ;
2214+ trackStatus.requestID = RequestID (2 );
2215+
2216+ withSessionContext (clientSession, [&]() {
2217+ auto task = relay_->trackStatus (trackStatus);
2218+ auto res = folly::coro::blockingWait (std::move (task), exec_.get ());
2219+
2220+ // Should return status from local forwarder
2221+ // Since no data was sent, statusCode should be TRACK_NOT_STARTED
2222+ EXPECT_TRUE (res.hasValue ());
2223+ EXPECT_EQ (res.value ().statusCode , TrackStatusCode::TRACK_NOT_STARTED );
2224+ EXPECT_EQ (res.value ().fullTrackName , kTestTrackName );
2225+ });
2226+
2227+ removeSession (clientSession);
2228+ exec_->drive ();
2229+ removeSession (publisherSession);
2230+ }
2231+
2232+ // Test: TrackStatus using namespace prefix matching (no exact subscription)
2233+ // Verifies that when there's no exact subscription but a publisher has
2234+ // published a matching namespace prefix, the relay correctly routes
2235+ // TRACK_STATUS upstream using prefix matching
2236+ TEST_F (MoQRelayTest, TrackStatusViaPrefixMatching) {
2237+ auto publisher = createMockSession ();
2238+ auto requester = createMockSession ();
2239+
2240+ // Publisher publishes namespace but NOT the specific track
2241+ doPublishNamespace (publisher, kTestNamespace );
2242+
2243+ // No exact subscription exists for kTestTrackName, so trackStatus should
2244+ // use prefix matching to find the publisher
2245+
2246+ // Mock the upstream trackStatus call
2247+ TrackStatusOk statusOk;
2248+ statusOk.requestID = RequestID (1 );
2249+ statusOk.trackAlias = TrackAlias (0 );
2250+ statusOk.largest = AbsoluteLocation{50 , 25 };
2251+
2252+ EXPECT_CALL (*publisher, trackStatus (_)).WillOnce ([statusOk](auto /* ts*/ ) {
2253+ return folly::coro::makeTask<Publisher::TrackStatusResult>(statusOk);
2254+ });
2255+
2256+ // Execute trackStatus from requester's perspective
2257+ TrackStatus trackStatus;
2258+ trackStatus.requestID = RequestID (1 );
2259+ trackStatus.fullTrackName = kTestTrackName ;
2260+
2261+ withSessionContext (requester, [&]() {
2262+ auto task = relay_->trackStatus (trackStatus);
2263+ auto result = folly::coro::blockingWait (std::move (task), exec_.get ());
2264+
2265+ // Should successfully forward via prefix matching and return the result
2266+ EXPECT_TRUE (result.hasValue ())
2267+ << " TrackStatus via namespace prefix matching should succeed" ;
2268+ EXPECT_EQ (result.value ().requestID , RequestID (1 ));
2269+ EXPECT_TRUE (result.value ().largest .has_value ());
2270+ EXPECT_EQ (result.value ().largest ->group , 50 );
2271+ EXPECT_EQ (result.value ().largest ->object , 25 );
2272+ });
2273+
2274+ removeSession (publisher);
2275+ removeSession (requester);
2276+ }
2277+
21792278} // namespace moxygen::test
0 commit comments