diff --git a/runtime/executor/method_meta.cpp b/runtime/executor/method_meta.cpp index 79aa681134f..400dfda9d0e 100644 --- a/runtime/executor/method_meta.cpp +++ b/runtime/executor/method_meta.cpp @@ -539,7 +539,13 @@ Result MethodMeta::get_backend_name(size_t index) const { "Index %zu out of range. num_backends: %zu", index, count); - return s_plan_->delegates()->Get(index)->id()->c_str(); + const auto delegate = s_plan_->delegates()->Get(index); + ET_CHECK_OR_RETURN_ERROR( + delegate != nullptr && delegate->id() != nullptr, + InvalidProgram, + "Missing backend id at index %zu", + index); + return delegate->id()->c_str(); } size_t MethodMeta::num_instructions() const { diff --git a/runtime/executor/test/method_meta_test.cpp b/runtime/executor/test/method_meta_test.cpp index fb05f7dfd56..700a0e20691 100644 --- a/runtime/executor/test/method_meta_test.cpp +++ b/runtime/executor/test/method_meta_test.cpp @@ -284,10 +284,13 @@ TEST_F(MethodMetaTest, MethodMetaBufferDeviceReturnsCudaForDeviceBuffer) { Error::InvalidArgument); } -TEST_F(MethodMetaTest, UsesBackendOnUnsetDelegatesReturnsFalse) { - // Construct a minimal schema-valid FlatBuffer program where delegates is - // unset (nullptr). - flatbuffers::FlatBufferBuilder fbb; +// Builds a minimal schema-valid FlatBuffer program whose "forward" plan has +// `delegates`, which may be null to leave them unset. +std::vector program_with_delegates( + flatbuffers::FlatBufferBuilder& fbb, + const std::vector< + flatbuffers::Offset>* + delegates) { std::vector empty_inputs = {}; std::vector empty_outputs = {}; std::vector non_const_buffer_sizes = {0}; @@ -300,7 +303,7 @@ TEST_F(MethodMetaTest, UsesBackendOnUnsetDelegatesReturnsFalse) { /*outputs=*/&empty_outputs, /*chains=*/nullptr, /*operators=*/nullptr, - /*delegates=*/nullptr, + /*delegates=*/delegates, /*non_const_buffer_sizes=*/&non_const_buffer_sizes, /*non_const_buffer_device=*/nullptr); std::vector> plans = @@ -328,6 +331,13 @@ TEST_F(MethodMetaTest, UsesBackendOnUnsetDelegatesReturnsFalse) { if (buffer.size() < Program::kMinHeadBytes) { buffer.resize(Program::kMinHeadBytes, 0); } + return buffer; +} + +TEST_F(MethodMetaTest, UsesBackendOnUnsetDelegatesReturnsFalse) { + flatbuffers::FlatBufferBuilder fbb; + std::vector buffer = + program_with_delegates(fbb, /*delegates=*/nullptr); BufferDataLoader loader(buffer.data(), buffer.size()); Result prog = Program::load(&loader, Program::Verification::Minimal); @@ -338,3 +348,20 @@ TEST_F(MethodMetaTest, UsesBackendOnUnsetDelegatesReturnsFalse) { EXPECT_FALSE(method_meta->uses_backend("xnnpack")); } + +TEST_F(MethodMetaTest, GetBackendNameOfDelegateWithoutIdReturnsError) { + flatbuffers::FlatBufferBuilder fbb; + std::vector> + delegates = {executorch_flatbuffer::CreateBackendDelegate(fbb)}; + std::vector buffer = program_with_delegates(fbb, &delegates); + + BufferDataLoader loader(buffer.data(), buffer.size()); + Result prog = Program::load(&loader, Program::Verification::Minimal); + ASSERT_EQ(prog.error(), Error::Ok); + + Result method_meta = prog->method_meta("forward"); + ASSERT_EQ(method_meta.error(), Error::Ok); + + ASSERT_EQ(method_meta->num_backends(), 1); + EXPECT_EQ(method_meta->get_backend_name(0).error(), Error::InvalidProgram); +}