Document graph service usage with docs and unit tests.
PiperOrigin-RevId: 513955877
This commit is contained in:
parent
3854d9fcd5
commit
9c3abcd06f
|
@ -1533,6 +1533,7 @@ cc_test(
|
|||
"//mediapipe/framework/port:parse_text_proto",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/framework/port:status_matchers",
|
||||
"//mediapipe/framework/tool:sink",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -141,6 +141,12 @@ class CalculatorContract {
|
|||
class GraphServiceRequest {
|
||||
public:
|
||||
// APIs that should be used by calculators.
|
||||
//
|
||||
// Indicates that requested service is optional and calculator can operate
|
||||
// correctly without it.
|
||||
//
|
||||
// NOTE: `CalculatorGraph` will still try to create services which allow
|
||||
// default initialization. (See `CalculatorGraph::UseService`)
|
||||
GraphServiceRequest& Optional() {
|
||||
optional_ = true;
|
||||
return *this;
|
||||
|
@ -158,6 +164,17 @@ class CalculatorContract {
|
|||
bool optional_ = false;
|
||||
};
|
||||
|
||||
// Indicates specific `service` is required for graph execution.
|
||||
//
|
||||
// For services which allow default initialization:
|
||||
// - `CalculatorGraph` will try to create corresponding service object by
|
||||
// default even if request is made optional
|
||||
// (`GraphServiceRequest::Optional()`)
|
||||
//
|
||||
// For services which disallow default initialization:
|
||||
// - `CalculatorGraph` requires client to set corresponding service object and
|
||||
// otherwise fails, unles request is mad optional
|
||||
// (`GraphServiceRequest::Optional()`)
|
||||
GraphServiceRequest& UseService(const GraphServiceBase& service) {
|
||||
auto it = service_requests_.emplace(service.key, service).first;
|
||||
return it->second;
|
||||
|
|
|
@ -157,5 +157,191 @@ TEST_F(GraphServiceTest, CreateDefault) {
|
|||
MP_EXPECT_OK(kNeedsCreateService.CreateDefaultObject());
|
||||
}
|
||||
|
||||
struct TestServiceData {};
|
||||
|
||||
const GraphService<TestServiceData> kTestServiceAllowDefaultInitialization(
|
||||
"kTestServiceAllowDefaultInitialization",
|
||||
GraphServiceBase::kAllowDefaultInitialization);
|
||||
|
||||
// This is only for test purposes. Ideally, a calculator that fails when service
|
||||
// is not available, should request the service as non-Optional.
|
||||
class FailOnUnavailableOptionalServiceCalculator : public CalculatorBase {
|
||||
public:
|
||||
static absl::Status GetContract(CalculatorContract* cc) {
|
||||
cc->UseService(kTestServiceAllowDefaultInitialization).Optional();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Open(CalculatorContext* cc) final {
|
||||
RET_CHECK(cc->Service(kTestServiceAllowDefaultInitialization).IsAvailable())
|
||||
<< "Service is unavailable.";
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Process(CalculatorContext* cc) final { return absl::OkStatus(); }
|
||||
};
|
||||
REGISTER_CALCULATOR(FailOnUnavailableOptionalServiceCalculator);
|
||||
|
||||
// Documents and ensures current behavior for requesting optional
|
||||
// "AllowDefaultInitialization" services:
|
||||
// - Service object is created by default.
|
||||
TEST(AllowDefaultInitializationGraphServiceTest,
|
||||
ServiceIsAvailableWithOptionalUse) {
|
||||
CalculatorGraphConfig config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"pb(
|
||||
node { calculator: 'FailOnUnavailableOptionalServiceCalculator' }
|
||||
)pb");
|
||||
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
MP_EXPECT_OK(graph.WaitUntilIdle());
|
||||
}
|
||||
|
||||
// Documents and ensures current behavior for setting `nullptr` service objects
|
||||
// for "AllowDefaultInitialization" optional services.
|
||||
// - It's allowed.
|
||||
// - It disables creation of "AllowDefaultInitialization" service objects, hence
|
||||
// results in optional service unavailability.
|
||||
TEST(AllowDefaultInitializationGraphServiceTest,
|
||||
NullServiceObjectIsAllowAndResultsInOptionalServiceUnavailability) {
|
||||
CalculatorGraphConfig config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"pb(
|
||||
node { calculator: 'FailOnUnavailableOptionalServiceCalculator' }
|
||||
)pb");
|
||||
|
||||
CalculatorGraph graph;
|
||||
std::shared_ptr<TestServiceData> object = nullptr;
|
||||
MP_ASSERT_OK(
|
||||
graph.SetServiceObject(kTestServiceAllowDefaultInitialization, object));
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
EXPECT_THAT(graph.WaitUntilIdle(),
|
||||
StatusIs(absl::StatusCode::kInternal,
|
||||
HasSubstr("Service is unavailable.")));
|
||||
}
|
||||
|
||||
class FailOnUnavailableServiceCalculator : public CalculatorBase {
|
||||
public:
|
||||
static absl::Status GetContract(CalculatorContract* cc) {
|
||||
cc->UseService(kTestServiceAllowDefaultInitialization);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Open(CalculatorContext* cc) final {
|
||||
RET_CHECK(cc->Service(kTestServiceAllowDefaultInitialization).IsAvailable())
|
||||
<< "Service is unavailable.";
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Process(CalculatorContext* cc) final { return absl::OkStatus(); }
|
||||
};
|
||||
REGISTER_CALCULATOR(FailOnUnavailableServiceCalculator);
|
||||
|
||||
// Documents and ensures current behavior for requesting optional
|
||||
// "AllowDefaultInitialization" services:
|
||||
// - Service object is created by default.
|
||||
TEST(AllowDefaultInitializationGraphServiceTest, ServiceIsAvailable) {
|
||||
CalculatorGraphConfig config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"pb(
|
||||
node { calculator: 'FailOnUnavailableServiceCalculator' }
|
||||
)pb");
|
||||
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
MP_EXPECT_OK(graph.WaitUntilIdle());
|
||||
}
|
||||
|
||||
// Documents and ensures current behavior for setting `nullptr` service objects
|
||||
// for "AllowDefaultInitialization" services.
|
||||
// - It's allowed.
|
||||
// - It disables creation of "AllowDefaultInitialization" service objects, hence
|
||||
// in service unavaialbility.
|
||||
TEST(AllowDefaultInitializationGraphServiceTest,
|
||||
NullServiceObjectIsAllowAndResultsInServiceUnavailability) {
|
||||
CalculatorGraphConfig config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"pb(
|
||||
node { calculator: 'FailOnUnavailableServiceCalculator' }
|
||||
)pb");
|
||||
|
||||
CalculatorGraph graph;
|
||||
std::shared_ptr<TestServiceData> object = nullptr;
|
||||
MP_ASSERT_OK(
|
||||
graph.SetServiceObject(kTestServiceAllowDefaultInitialization, object));
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
EXPECT_THAT(graph.WaitUntilIdle(),
|
||||
StatusIs(absl::StatusCode::kInternal,
|
||||
HasSubstr("Service is unavailable.")));
|
||||
}
|
||||
|
||||
const GraphService<TestServiceData> kTestServiceDisallowDefaultInitialization(
|
||||
"kTestServiceDisallowDefaultInitialization",
|
||||
GraphServiceBase::kDisallowDefaultInitialization);
|
||||
|
||||
class FailOnUnavailableOptionalDisallowDefaultInitServiceCalculator
|
||||
: public CalculatorBase {
|
||||
public:
|
||||
static absl::Status GetContract(CalculatorContract* cc) {
|
||||
cc->UseService(kTestServiceDisallowDefaultInitialization).Optional();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Open(CalculatorContext* cc) final {
|
||||
RET_CHECK(
|
||||
cc->Service(kTestServiceDisallowDefaultInitialization).IsAvailable())
|
||||
<< "Service is unavailable.";
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Process(CalculatorContext* cc) final { return absl::OkStatus(); }
|
||||
};
|
||||
REGISTER_CALCULATOR(
|
||||
FailOnUnavailableOptionalDisallowDefaultInitServiceCalculator);
|
||||
|
||||
// Documents and ensures current behavior for requesting optional
|
||||
// "DisallowDefaultInitialization" services:
|
||||
// - Service object is not created by default.
|
||||
TEST(DisallowDefaultInitializationGraphServiceTest,
|
||||
ServiceIsUnavailableWithOptionalUse) {
|
||||
CalculatorGraphConfig config = mediapipe::ParseTextProtoOrDie<
|
||||
CalculatorGraphConfig>(R"pb(
|
||||
node {
|
||||
calculator: 'FailOnUnavailableOptionalDisallowDefaultInitServiceCalculator'
|
||||
}
|
||||
)pb");
|
||||
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
EXPECT_THAT(graph.WaitUntilIdle(),
|
||||
StatusIs(absl::StatusCode::kInternal,
|
||||
HasSubstr("Service is unavailable.")));
|
||||
}
|
||||
|
||||
class UseDisallowDefaultInitServiceCalculator : public CalculatorBase {
|
||||
public:
|
||||
static absl::Status GetContract(CalculatorContract* cc) {
|
||||
cc->UseService(kTestServiceDisallowDefaultInitialization);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
absl::Status Open(CalculatorContext* cc) final { return absl::OkStatus(); }
|
||||
absl::Status Process(CalculatorContext* cc) final { return absl::OkStatus(); }
|
||||
};
|
||||
REGISTER_CALCULATOR(UseDisallowDefaultInitServiceCalculator);
|
||||
|
||||
// Documents and ensures current behavior for requesting
|
||||
// "DisallowDefaultInitialization" services:
|
||||
// - Service object is not created by default.
|
||||
// - Graph run fails.
|
||||
TEST(DisallowDefaultInitializationGraphServiceTest,
|
||||
StartRunFailsMissingService) {
|
||||
CalculatorGraphConfig config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"pb(
|
||||
node { calculator: 'UseDisallowDefaultInitServiceCalculator' }
|
||||
)pb");
|
||||
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
EXPECT_THAT(graph.StartRun({}),
|
||||
StatusIs(absl::StatusCode::kInternal,
|
||||
HasSubstr("was not provided and cannot be created")));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
|
|
Loading…
Reference in New Issue
Block a user