TensorFlow Serving C++ API Documentation
unique_ptr_with_deps_test.cc
1 /* Copyright 2016 Google Inc. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7  http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow_serving/util/unique_ptr_with_deps.h"
17 
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include <gtest/gtest.h>
23 
24 namespace tensorflow {
25 namespace serving {
26 namespace {
27 
28 // Trait to select overloads and return types for MakeUnique.
29 template <typename T>
30 struct MakeUniqueResult {
31  using scalar = std::unique_ptr<T>;
32 };
33 
34 // MakeUnique<T>(...) is an early implementation of C++14 std::make_unique.
35 // It is designed to be 100% compatible with std::make_unique so that the
36 // eventual switchover will be a simple renaming operation.
37 template <typename T, typename... Args>
38 typename MakeUniqueResult<T>::scalar MakeUnique(Args&&... args) { // NOLINT
39  return std::unique_ptr<T>(
40  new T(std::forward<Args>(args)...)); // NOLINT(build/c++11)
41 }
42 
43 class Dep {
44  public:
45  Dep(const string& name, std::vector<string>* log) : name_(name), log_(log) {}
46  ~Dep() { log_->push_back("Deleting " + name_); }
47  void f() { log_->push_back(name_ + ".f() called"); }
48 
49  private:
50  string name_;
51  std::vector<string>* log_;
52 };
53 
54 // Create another class just to show that dependencies can have different type
55 // than main object.
56 class Obj {
57  public:
58  Obj(const string& name, std::vector<string>* log) : name_(name), log_(log) {}
59  ~Obj() { log_->push_back("Deleting " + name_); }
60  void f() const { log_->push_back("Obj::f() called on " + name_); }
61 
62  private:
63  string name_;
64  std::vector<string>* log_;
65 };
66 
67 UniquePtrWithDeps<Obj> BuildObjWithDeps(std::vector<string>* log) {
68  UniquePtrWithDeps<Obj> obj;
69  auto dep1 = obj.AddDependency(MakeUnique<Dep>("dep1", log));
70  auto dep2 = obj.AddDependency(MakeUnique<Dep>("dep2", log));
71  auto dep3 = obj.AddDependency(MakeUnique<Dep>("dep3", log));
72  dep1->f();
73  dep2->f();
74  dep3->f();
75  obj.SetOwned(MakeUnique<Obj>("obj", log));
76  return obj;
77 }
78 
79 TEST(UniquePtrWithDepsTest, DependenciesDestroyedAfterMainObject) {
80  std::vector<string> log;
81  {
82  auto obj = BuildObjWithDeps(&log);
83  obj->f();
84  }
85  EXPECT_EQ(std::vector<string>({"dep1.f() called",
86  "dep2.f() called",
87  "dep3.f() called",
88  "Obj::f() called on obj",
89  "Deleting obj",
90  "Deleting dep3",
91  "Deleting dep2",
92  "Deleting dep1"}),
93  log);
94 }
95 
96 UniquePtrWithDeps<Obj> BuildObjWithDepAddedLater(std::vector<string>* log) {
97  UniquePtrWithDeps<Obj> obj;
98  obj.SetOwned(MakeUnique<Obj>("obj", log));
99  auto dep = obj.AddDependency(MakeUnique<Dep>("dep", log));
100  dep->f();
101  return obj;
102 }
103 
104 TEST(UniquePtrWithDepsTest, DependencyAddedAfterSetOwned) {
105  std::vector<string> log;
106  {
107  auto obj = BuildObjWithDepAddedLater(&log);
108  obj->f();
109  }
110  EXPECT_EQ(std::vector<string>({"dep.f() called",
111  "Obj::f() called on obj",
112  "Deleting dep",
113  "Deleting obj"}),
114  log);
115 }
116 
117 UniquePtrWithDeps<Obj> BuildObjWithDepsMultipleSetOwned(
118  std::vector<string>* log) {
119  UniquePtrWithDeps<Obj> obj;
120  auto dep1 = obj.AddDependency(MakeUnique<Dep>("dep1", log));
121  obj.SetOwned(MakeUnique<Obj>("obj1", log));
122  auto dep2 = obj.AddDependency(MakeUnique<Dep>("dep2", log));
123  auto dep3 = obj.AddDependency(MakeUnique<Dep>("dep3", log));
124  dep1->f();
125  dep2->f();
126  dep3->f();
127  obj.SetOwned(MakeUnique<Obj>("obj2", log));
128  return obj;
129 }
130 
131 TEST(UniquePtrWithDepsTest, MultipleSetOwnedCalls) {
132  std::vector<string> log;
133  {
134  auto obj = BuildObjWithDepsMultipleSetOwned(&log);
135  obj->f();
136  }
137  EXPECT_EQ(std::vector<string>({"dep1.f() called",
138  "dep2.f() called",
139  "dep3.f() called",
140  "Obj::f() called on obj2",
141  "Deleting obj2",
142  "Deleting dep3",
143  "Deleting dep2",
144  "Deleting obj1",
145  "Deleting dep1"}),
146  log);
147 }
148 
149 } // namespace
150 } // namespace serving
151 } // namespace tensorflow