diff --git a/backend/src/plugins/telemetry/telemetry_service_impl.h b/backend/src/plugins/telemetry/telemetry_service_impl.h index 0416bc123f..0b5f0d6ecf 100644 --- a/backend/src/plugins/telemetry/telemetry_service_impl.h +++ b/backend/src/plugins/telemetry/telemetry_service_impl.h @@ -92,6 +92,20 @@ class TelemetryServiceImpl final : public dronecore::rpc::telemetry::TelemetrySe return grpc::Status::OK; } + grpc::Status SubscribeArmed(grpc::ServerContext * /* context */, + const dronecore::rpc::telemetry::SubscribeArmedRequest * /* request */, + grpc::ServerWriter *writer) override + { + _telemetry.armed_async([&writer](bool is_armed) { + dronecore::rpc::telemetry::ArmedResponse rpc_armed_response; + rpc_armed_response.set_is_armed(is_armed); + writer->Write(rpc_armed_response); + }); + + _stop_future.wait(); + return grpc::Status::OK; + } + void stop() { _stop_promise.set_value(); diff --git a/backend/test/telemetry_service_impl_test.cpp b/backend/test/telemetry_service_impl_test.cpp index db4d4f42ca..a737426d82 100644 --- a/backend/test/telemetry_service_impl_test.cpp +++ b/backend/test/telemetry_service_impl_test.cpp @@ -66,6 +66,9 @@ class TelemetryServiceImplTest : public ::testing::Test void checkSendsInAirEvents(const std::vector &in_air_events) const; std::future subscribeInAirAsync(std::vector &in_air_events) const; + void checkSendsArmedEvents(const std::vector &armed_events) const; + std::future subscribeArmedAsync(std::vector &armed_events) const; + std::unique_ptr _server; std::unique_ptr _stub; std::unique_ptr _telemetry; @@ -363,7 +366,8 @@ TEST_F(TelemetryServiceImplTest, sendsOneHome) checkSendsHomePositions(home_positions); } -void TelemetryServiceImplTest::checkSendsHomePositions(const std::vector &home_positions) const +void TelemetryServiceImplTest::checkSendsHomePositions(const std::vector &home_positions) +const { std::promise subscription_promise; auto subscription_future = subscription_promise.get_future(); @@ -408,7 +412,8 @@ TEST_F(TelemetryServiceImplTest, registersToTelemetryInAirAsync) in_air_stream_future.wait(); } -std::future TelemetryServiceImplTest::subscribeInAirAsync(std::vector &in_air_events) const +std::future TelemetryServiceImplTest::subscribeInAirAsync(std::vector &in_air_events) +const { return std::async(std::launch::async, [&]() { grpc::ClientContext context; @@ -478,4 +483,87 @@ TEST_F(TelemetryServiceImplTest, sendsMultipleInAirEvents) checkSendsInAirEvents(in_air_events); } +TEST_F(TelemetryServiceImplTest, registersToTelemetryArmedAsync) +{ + EXPECT_CALL(*_telemetry, armed_async(_)) + .Times(1); + + std::vector armed_events; + auto armed_stream_future = subscribeArmedAsync(armed_events); + + _telemetry_service->stop(); + armed_stream_future.wait(); +} + +std::future +TelemetryServiceImplTest::subscribeArmedAsync(std::vector &armed_events) const +{ + return std::async(std::launch::async, [&]() { + grpc::ClientContext context; + dronecore::rpc::telemetry::SubscribeArmedRequest request; + auto response_reader = _stub->SubscribeArmed(&context, request); + + dronecore::rpc::telemetry::ArmedResponse response; + while (response_reader->Read(&response)) { + auto is_armed = response.is_armed(); + armed_events.push_back(is_armed); + } + + response_reader->Finish(); + }); +} + +TEST_F(TelemetryServiceImplTest, doesNotSendArmedIfCallbackNotCalled) +{ + std::vector armed_events; + auto armed_stream_future = subscribeArmedAsync(armed_events); + + _telemetry_service->stop(); + armed_stream_future.wait(); + + EXPECT_EQ(0, armed_events.size()); +} + +TEST_F(TelemetryServiceImplTest, sendsOneArmedEvent) +{ + std::vector armed_events; + armed_events.push_back(generateRandomBool()); + + checkSendsInAirEvents(armed_events); +} + +void TelemetryServiceImplTest::checkSendsArmedEvents(const std::vector &armed_events) const +{ + std::promise subscription_promise; + auto subscription_future = subscription_promise.get_future(); + dronecore::Telemetry::armed_callback_t armed_callback; + EXPECT_CALL(*_telemetry, armed_async(_)) + .WillOnce(SaveCallback(&armed_callback, &subscription_promise)); + + std::vector received_armed_events; + auto armed_stream_future = subscribeArmedAsync(received_armed_events); + subscription_future.wait(); + for (const auto is_armed : armed_events) { + armed_callback(is_armed); + } + _telemetry_service->stop(); + armed_stream_future.wait(); + + ASSERT_EQ(armed_events.size(), received_armed_events.size()); + for (size_t i = 0; i < armed_events.size(); i++) { + EXPECT_EQ(armed_events.at(i), received_armed_events.at(i)); + } +} + +TEST_F(TelemetryServiceImplTest, sendsMultipleArmedEvents) +{ + std::vector armed_events; + + for (int i = 0; i < 10; i++) { + armed_events.push_back(generateRandomBool()); + } + + checkSendsArmedEvents(armed_events); +} + } // namespace diff --git a/plugins/telemetry/mocks/telemetry_mock.h b/plugins/telemetry/mocks/telemetry_mock.h index 3262316a7a..0aab1c9431 100644 --- a/plugins/telemetry/mocks/telemetry_mock.h +++ b/plugins/telemetry/mocks/telemetry_mock.h @@ -12,6 +12,7 @@ class MockTelemetry MOCK_CONST_METHOD1(health_async, void(Telemetry::health_callback_t)); MOCK_CONST_METHOD1(home_position_async, void(Telemetry::position_callback_t)); MOCK_CONST_METHOD1(in_air_async, void(Telemetry::in_air_callback_t)); + MOCK_CONST_METHOD1(armed_async, void(Telemetry::armed_callback_t)); }; } // namespace testing