16 #include "tensorflow_serving/resources/resource_tracker.h"
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include "tensorflow/core/lib/core/status.h"
25 #include "tensorflow/core/lib/core/status_test_util.h"
26 #include "tensorflow/core/platform/types.h"
27 #include "tensorflow_serving/core/test_util/mock_loader.h"
28 #include "tensorflow_serving/resources/resources.pb.h"
29 #include "tensorflow_serving/test_util/test_util.h"
30 #include "tensorflow_serving/util/any_ptr.h"
32 using ::tensorflow::serving::test_util::CreateProto;
33 using ::tensorflow::serving::test_util::EqualsProto;
35 using ::testing::Invoke;
36 using ::testing::NiceMock;
38 namespace tensorflow {
42 class ResourceTrackerTest :
public ::testing::Test {
46 CreateProto<ResourceAllocation>(
"resource_quantities { "
49 " device_instance { value: 0 } "
54 "resource_quantities { "
57 " device_instance { value: 0 } "
62 "resource_quantities { "
65 " device_instance { value: 1 } "
70 std::unique_ptr<ResourceUtil> util(
71 new ResourceUtil({{{
"main", 1}, {
"gpu", 2}}}));
72 TF_CHECK_OK(ResourceTracker::Create(
73 total_resources_, std::unique_ptr<ResourceUtil>(std::move(util)),
76 loader_0_.reset(
new NiceMock<test_util::MockLoader>);
77 ON_CALL(*loader_0_, EstimateResources(_))
78 .WillByDefault(Invoke([](ResourceAllocation* estimate) {
79 *estimate = CreateProto<ResourceAllocation>(
80 "resource_quantities { "
87 "resource_quantities { "
90 " device_instance { value: 0 } "
98 loader_1_.reset(
new NiceMock<test_util::MockLoader>);
99 ON_CALL(*loader_1_, EstimateResources(_))
100 .WillByDefault(Invoke([](ResourceAllocation* estimate) {
101 *estimate = CreateProto<ResourceAllocation>(
102 "resource_quantities { "
109 "resource_quantities { "
112 " device_instance { value: 0 } "
120 loader_2_.reset(
new NiceMock<test_util::MockLoader>);
121 ON_CALL(*loader_2_, EstimateResources(_))
122 .WillByDefault(Invoke([](ResourceAllocation* estimate) {
123 *estimate = CreateProto<ResourceAllocation>(
124 "resource_quantities { "
134 loader_3_.reset(
new NiceMock<test_util::MockLoader>);
135 ON_CALL(*loader_3_, EstimateResources(_))
136 .WillByDefault(Invoke([](ResourceAllocation* estimate) {
137 *estimate = CreateProto<ResourceAllocation>(
138 "resource_quantities { "
148 invalid_resources_loader_.reset(
new NiceMock<test_util::MockLoader>);
149 ON_CALL(*invalid_resources_loader_, EstimateResources(_))
150 .WillByDefault(Invoke([](ResourceAllocation* estimate) {
151 *estimate = CreateProto<ResourceAllocation>(
152 "resource_quantities { "
154 " device: 'bogus_device' "
155 " device_instance { value: 0 } "
164 for (
auto* loader : {loader_0_.get(), loader_1_.get(), loader_2_.get(),
165 loader_3_.get(), invalid_resources_loader_.get()}) {
166 EXPECT_CALL(*loader, Load()).Times(0);
167 EXPECT_CALL(*loader, Unload()).Times(0);
172 const ResourceAllocation total_resources_;
175 std::unique_ptr<ResourceTracker> tracker_;
178 std::unique_ptr<test_util::MockLoader> loader_0_;
179 std::unique_ptr<test_util::MockLoader> loader_1_;
180 std::unique_ptr<test_util::MockLoader> loader_2_;
181 std::unique_ptr<test_util::MockLoader> loader_3_;
182 std::unique_ptr<test_util::MockLoader> invalid_resources_loader_;
185 TEST_F(ResourceTrackerTest, UnboundTotalResources) {
186 std::unique_ptr<ResourceUtil> util(
187 new ResourceUtil({{{
"main", 1}, {
"gpu", 2}}}));
188 std::unique_ptr<ResourceTracker> tracker;
189 const auto unbound_resources = CreateProto<ResourceAllocation>(
190 "resource_quantities { "
197 EXPECT_FALSE(ResourceTracker::Create(
199 std::unique_ptr<ResourceUtil>(std::move(util)), &tracker)
203 TEST_F(ResourceTrackerTest, UnnormalizedTotalResources) {
204 std::unique_ptr<ResourceUtil> util(
205 new ResourceUtil({{{
"main", 1}, {
"gpu", 2}}}));
206 std::unique_ptr<ResourceTracker> tracker;
207 const auto unnormalized_resources = CreateProto<ResourceAllocation>(
208 "resource_quantities { "
215 TF_ASSERT_OK(ResourceTracker::Create(
216 unnormalized_resources, std::unique_ptr<ResourceUtil>(std::move(util)),
219 EXPECT_THAT(tracker->total_resources(),
220 EqualsProto(
"resource_quantities { "
223 " device_instance { value: 0 } "
230 TEST_F(ResourceTrackerTest, RecomputeUsedResources) {
232 EXPECT_THAT(tracker_->used_resources(), EqualsProto(
""));
233 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
236 TF_ASSERT_OK(tracker_->RecomputeUsedResources(
237 {loader_0_.get(), loader_1_.get(), loader_3_.get()}));
238 EXPECT_THAT(tracker_->used_resources(),
239 EqualsProto(
"resource_quantities { "
242 " device_instance { value: 0 } "
247 "resource_quantities { "
250 " device_instance { value: 0 } "
255 "resource_quantities { "
262 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
265 TF_ASSERT_OK(tracker_->RecomputeUsedResources({loader_0_.get()}));
266 EXPECT_THAT(tracker_->used_resources(),
267 EqualsProto(
"resource_quantities { "
270 " device_instance { value: 0 } "
275 "resource_quantities { "
278 " device_instance { value: 0 } "
283 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
286 TEST_F(ResourceTrackerTest, ReserveResourcesSuccessWithUsedResourcesBound) {
287 TF_ASSERT_OK(tracker_->RecomputeUsedResources({loader_0_.get()}));
288 EXPECT_THAT(tracker_->used_resources(),
289 EqualsProto(
"resource_quantities { "
292 " device_instance { value: 0 } "
297 "resource_quantities { "
300 " device_instance { value: 0 } "
308 TF_ASSERT_OK(tracker_->ReserveResources(*loader_2_, &success));
309 EXPECT_TRUE(success);
310 EXPECT_THAT(tracker_->used_resources(),
311 EqualsProto(
"resource_quantities { "
314 " device_instance { value: 0 } "
319 "resource_quantities { "
322 " device_instance { value: 0 } "
327 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
330 TEST_F(ResourceTrackerTest, ReserveResourcesFailureWithUsedResourcesBound) {
331 TF_ASSERT_OK(tracker_->RecomputeUsedResources({loader_1_.get()}));
332 EXPECT_THAT(tracker_->used_resources(),
333 EqualsProto(
"resource_quantities { "
336 " device_instance { value: 0 } "
341 "resource_quantities { "
344 " device_instance { value: 0 } "
352 TF_ASSERT_OK(tracker_->ReserveResources(*loader_2_, &success));
353 EXPECT_FALSE(success);
355 EXPECT_THAT(tracker_->used_resources(),
356 EqualsProto(
"resource_quantities { "
359 " device_instance { value: 0 } "
364 "resource_quantities { "
367 " device_instance { value: 0 } "
372 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
375 TEST_F(ResourceTrackerTest, ReserveResourcesSuccessWithUsedResourcesUnbound) {
376 TF_ASSERT_OK(tracker_->RecomputeUsedResources({loader_3_.get()}));
377 EXPECT_THAT(tracker_->used_resources(), EqualsProto(
"resource_quantities { "
387 TF_ASSERT_OK(tracker_->ReserveResources(*loader_0_, &success));
388 EXPECT_TRUE(success);
389 EXPECT_THAT(tracker_->used_resources(),
390 EqualsProto(
"resource_quantities { "
397 "resource_quantities { "
400 " device_instance { value: 0 } "
405 "resource_quantities { "
408 " device_instance { value: 0 } "
413 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
416 TEST_F(ResourceTrackerTest, ReserveResourcesFailureWithUsedResourcesUnbound) {
417 TF_ASSERT_OK(tracker_->RecomputeUsedResources({loader_3_.get()}));
418 EXPECT_THAT(tracker_->used_resources(), EqualsProto(
"resource_quantities { "
429 TF_ASSERT_OK(tracker_->ReserveResources(*loader_1_, &success));
430 EXPECT_FALSE(success);
431 TF_ASSERT_OK(tracker_->ReserveResources(*loader_3_, &success));
432 EXPECT_FALSE(success);
435 EXPECT_THAT(tracker_->used_resources(), EqualsProto(
"resource_quantities { "
442 EXPECT_THAT(tracker_->total_resources(), EqualsProto(total_resources_));
445 TEST_F(ResourceTrackerTest, InvalidResourceEstimate) {
448 tracker_->ReserveResources(*invalid_resources_loader_, &success).ok());
449 EXPECT_FALSE(tracker_
450 ->RecomputeUsedResources(
451 {loader_0_.get(), invalid_resources_loader_.get()})