| // Copyright 2018 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 "osp/impl/presentation/url_availability_requester.h" |
| |
| #include <chrono> |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "osp/impl/quic/quic_client.h" |
| #include "osp/impl/quic/testing/quic_test_support.h" |
| #include "osp/msgs/osp_messages.h" |
| #include "osp/public/network_service_manager.h" |
| #include "osp/public/testing/message_demuxer_test_support.h" |
| #include "platform/test/fake_clock.h" |
| #include "platform/test/fake_task_runner.h" |
| #include "util/osp_logging.h" |
| |
| namespace openscreen { |
| namespace osp { |
| |
| using ::testing::_; |
| using ::testing::Invoke; |
| using ::testing::Mock; |
| using ::testing::Test; |
| |
| namespace { |
| |
| class MockReceiverObserver : public ReceiverObserver { |
| public: |
| ~MockReceiverObserver() override = default; |
| |
| MOCK_METHOD2(OnRequestFailed, void(const std::string&, const std::string&)); |
| MOCK_METHOD2(OnReceiverAvailable, |
| void(const std::string&, const std::string&)); |
| MOCK_METHOD2(OnReceiverUnavailable, |
| void(const std::string&, const std::string&)); |
| }; |
| |
| } // namespace |
| |
| class UrlAvailabilityRequesterTest : public Test { |
| public: |
| UrlAvailabilityRequesterTest() { |
| fake_clock_ = std::make_unique<FakeClock>( |
| Clock::time_point(std::chrono::milliseconds(1298424))); |
| task_runner_ = std::make_unique<FakeTaskRunner>(fake_clock_.get()); |
| quic_bridge_ = |
| std::make_unique<FakeQuicBridge>(task_runner_.get(), FakeClock::now); |
| info1_ = {service_id_, friendly_name_, 1, quic_bridge_->kReceiverEndpoint}; |
| } |
| |
| void SetUp() override { |
| NetworkServiceManager::Create(nullptr, nullptr, |
| std::move(quic_bridge_->quic_client), |
| std::move(quic_bridge_->quic_server)); |
| availability_watch_ = |
| quic_bridge_->receiver_demuxer->SetDefaultMessageTypeWatch( |
| msgs::Type::kPresentationUrlAvailabilityRequest, &mock_callback_); |
| } |
| |
| void TearDown() override { |
| availability_watch_ = MessageDemuxer::MessageWatch(); |
| NetworkServiceManager::Dispose(); |
| } |
| |
| protected: |
| std::unique_ptr<ProtocolConnection> ExpectIncomingConnection() { |
| std::unique_ptr<ProtocolConnection> stream; |
| |
| EXPECT_CALL(quic_bridge_->mock_server_observer, OnIncomingConnectionMock(_)) |
| .WillOnce( |
| Invoke([&stream](std::unique_ptr<ProtocolConnection>& connection) { |
| stream = std::move(connection); |
| })); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| return stream; |
| } |
| |
| void ExpectStreamMessage(MockMessageCallback* mock_callback, |
| msgs::PresentationUrlAvailabilityRequest* request) { |
| EXPECT_CALL(*mock_callback, OnStreamMessage(_, _, _, _, _, _)) |
| .WillOnce( |
| Invoke([request](uint64_t endpoint_id, uint64_t cid, |
| msgs::Type message_type, const uint8_t* buffer, |
| size_t buffer_size, Clock::time_point now) { |
| ssize_t request_result_size = |
| msgs::DecodePresentationUrlAvailabilityRequest( |
| buffer, buffer_size, request); |
| OSP_DCHECK_GT(request_result_size, 0); |
| return request_result_size; |
| })); |
| } |
| |
| void SendAvailabilityResponse( |
| const msgs::PresentationUrlAvailabilityRequest& request, |
| std::vector<msgs::UrlAvailability>&& availabilities, |
| ProtocolConnection* stream) { |
| msgs::PresentationUrlAvailabilityResponse response; |
| response.request_id = request.request_id; |
| response.url_availabilities = std::move(availabilities); |
| msgs::CborEncodeBuffer buffer; |
| ssize_t encode_result = |
| msgs::EncodePresentationUrlAvailabilityResponse(response, &buffer); |
| ASSERT_GT(encode_result, 0); |
| stream->Write(buffer.data(), buffer.size()); |
| } |
| |
| void SendAvailabilityEvent( |
| uint64_t watch_id, |
| std::vector<msgs::UrlAvailability>&& availabilities, |
| ProtocolConnection* stream) { |
| msgs::PresentationUrlAvailabilityEvent event; |
| event.watch_id = watch_id; |
| event.url_availabilities = std::move(availabilities); |
| msgs::CborEncodeBuffer buffer; |
| ssize_t encode_result = |
| msgs::EncodePresentationUrlAvailabilityEvent(event, &buffer); |
| ASSERT_GT(encode_result, 0); |
| stream->Write(buffer.data(), buffer.size()); |
| } |
| |
| std::unique_ptr<FakeClock> fake_clock_; |
| std::unique_ptr<FakeTaskRunner> task_runner_; |
| MockMessageCallback mock_callback_; |
| MessageDemuxer::MessageWatch availability_watch_; |
| std::unique_ptr<FakeQuicBridge> quic_bridge_; |
| UrlAvailabilityRequester listener_{FakeClock::now}; |
| |
| std::string url1_{"https://example.com/foo.html"}; |
| std::string url2_{"https://example.com/bar.html"}; |
| std::string service_id_{"asdf"}; |
| std::string friendly_name_{"turtle"}; |
| ServiceInfo info1_; |
| }; |
| |
| TEST_F(UrlAvailabilityRequesterTest, AvailableObserverFirst) { |
| MockReceiverObserver mock_observer; |
| listener_.AddObserver({url1_}, &mock_observer); |
| |
| listener_.AddReceiver(info1_); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, AvailableReceiverFirst) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer; |
| listener_.AddObserver({url1_}, &mock_observer); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, Unavailable) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer; |
| listener_.AddObserver({url1_}, &mock_observer); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, AvailabilityIsCached) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)); |
| listener_.AddObserver({url1_}, &mock_observer2); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, AvailabilityCacheIsTransient) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| listener_.RemoveObserverUrls({url1_}, &mock_observer1); |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| listener_.AddObserver({url1_}, &mock_observer2); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, PartiallyCachedAnswer) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)); |
| listener_.AddObserver({url1_, url2_}, &mock_observer2); |
| |
| ExpectStreamMessage(&mock_callback_, &request); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| EXPECT_EQ(std::vector<std::string>{url2_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url2_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url2_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, MultipleOverlappingObservers) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)); |
| listener_.AddObserver({url1_, url2_}, &mock_observer2); |
| ExpectStreamMessage(&mock_callback_, &request); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| EXPECT_EQ(std::vector<std::string>{url2_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url2_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, RemoveObserverUrls) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| uint64_t url1_watch_id = request.watch_id; |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)); |
| listener_.AddObserver({url1_, url2_}, &mock_observer2); |
| |
| ExpectStreamMessage(&mock_callback_, &request); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| |
| EXPECT_EQ(std::vector<std::string>{url2_}, request.urls); |
| |
| listener_.RemoveObserverUrls({url1_}, &mock_observer1); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url2_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| |
| SendAvailabilityEvent( |
| url1_watch_id, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, RemoveObserver) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| uint64_t url1_watch_id = request.watch_id; |
| |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)); |
| listener_.AddObserver({url1_, url2_}, &mock_observer2); |
| |
| ExpectStreamMessage(&mock_callback_, &request); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| |
| uint64_t url2_watch_id = request.watch_id; |
| EXPECT_EQ(std::vector<std::string>{url2_}, request.urls); |
| |
| listener_.RemoveObserver(&mock_observer1); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url2_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| |
| SendAvailabilityEvent( |
| url1_watch_id, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| |
| listener_.RemoveObserver(&mock_observer2); |
| |
| SendAvailabilityEvent( |
| url1_watch_id, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| SendAvailabilityEvent( |
| url2_watch_id, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(_, service_id_)).Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| Mock::VerifyAndClearExpectations(&mock_observer1); |
| Mock::VerifyAndClearExpectations(&mock_observer2); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, EventUpdate) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_, url2_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ((std::vector<std::string>{url1_, url2_}), request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable, |
| msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url2_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(_, service_id_)).Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| EXPECT_CALL(mock_callback_, OnStreamMessage(_, _, _, _, _, _)).Times(0); |
| SendAvailabilityEvent( |
| request.watch_id, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable, |
| msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url2_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, RefreshWatches) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(_, service_id_)).Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| fake_clock_->Advance(std::chrono::seconds(60)); |
| |
| ExpectStreamMessage(&mock_callback_, &request); |
| listener_.RefreshWatches(); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, ResponseAfterRemoveObserver) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| listener_.RemoveObserverUrls({url1_}, &mock_observer1); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| listener_.AddObserver({url1_}, &mock_observer2); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, |
| EmptyCacheAfterRemoveObserverThenReceiver) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ(std::vector<std::string>{url1_}, request.urls); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| |
| listener_.RemoveObserverUrls({url1_}, &mock_observer1); |
| listener_.RemoveReceiver(info1_); |
| MockReceiverObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer2, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| listener_.AddObserver({url1_}, &mock_observer2); |
| } |
| |
| TEST_F(UrlAvailabilityRequesterTest, RemoveObserverInSteps) { |
| listener_.AddReceiver(info1_); |
| |
| MockReceiverObserver mock_observer1; |
| listener_.AddObserver({url1_, url2_}, &mock_observer1); |
| |
| msgs::PresentationUrlAvailabilityRequest request; |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| std::unique_ptr<ProtocolConnection> stream = ExpectIncomingConnection(); |
| ASSERT_TRUE(stream); |
| |
| EXPECT_EQ((std::vector<std::string>{url1_, url2_}), request.urls); |
| listener_.RemoveObserverUrls({url1_}, &mock_observer1); |
| listener_.RemoveObserverUrls({url2_}, &mock_observer1); |
| SendAvailabilityResponse( |
| request, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable, |
| msgs::UrlAvailability::kAvailable}, |
| stream.get()); |
| SendAvailabilityEvent( |
| request.watch_id, |
| std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kUnavailable, |
| msgs::UrlAvailability::kUnavailable}, |
| stream.get()); |
| |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url1_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url1_, service_id_)) |
| .Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverAvailable(url2_, service_id_)).Times(0); |
| EXPECT_CALL(mock_observer1, OnReceiverUnavailable(url2_, service_id_)) |
| .Times(0); |
| |
| // NOTE: This message was generated between the two RemoveObserverUrls calls |
| // above. So even though the request is internally cancelled almost |
| // immediately, this still went out on the wire. |
| ExpectStreamMessage(&mock_callback_, &request); |
| |
| quic_bridge_->RunTasksUntilIdle(); |
| EXPECT_EQ((std::vector<std::string>{url2_}), request.urls); |
| |
| fake_clock_->Advance(std::chrono::seconds(60)); |
| |
| listener_.RefreshWatches(); |
| EXPECT_CALL(mock_callback_, OnStreamMessage(_, _, _, _, _, _)).Times(0); |
| quic_bridge_->RunTasksUntilIdle(); |
| } |
| |
| } // namespace osp |
| } // namespace openscreen |