TensorFlow Serving C++ API Documentation
any_ptr_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/any_ptr.h"
17 
18 #include <memory>
19 #include <utility>
20 
21 #include <gtest/gtest.h>
22 #include "absl/base/attributes.h"
23 
24 namespace tensorflow {
25 namespace serving {
26 namespace {
27 
28 TEST(AnyPtrTest, SetAndGet) {
29  AnyPtr ptr;
30  int object;
31 
32  // Implicitly settable/constructable from a raw pointer.
33  ptr = &object;
34  EXPECT_EQ(&object, ptr.get<int>());
35  EXPECT_EQ(nullptr, ptr.get<bool>());
36 
37  // Implicitly settable/constructable from nullptr.
38  ptr = nullptr;
39  EXPECT_EQ(nullptr, ptr.get<int>());
40  EXPECT_EQ(nullptr, ptr.get<bool>());
41 }
42 
43 TEST(AnyPtrTest, ConstCorrect) {
44  AnyPtr ptr;
45  const int object = 0;
46  ptr = &object;
47  EXPECT_EQ(nullptr, ptr.get<int>());
48  EXPECT_EQ(&object, ptr.get<const int>());
49 }
50 
51 // Tests that a dynamic relationship between two classes doesn't cause any sort
52 // of type-punning.
53 TEST(AnyPtrTest, BaseClass) {
54  class Base {
55  public:
56  virtual ~Base() {}
57 
58  private:
59  int unused_base_var_ ABSL_ATTRIBUTE_UNUSED = 0;
60  };
61 
62  class Child : public Base {
63  public:
64  ~Child() override {}
65 
66  private:
67  int unused_child_var_ ABSL_ATTRIBUTE_UNUSED = 0;
68  };
69 
70  AnyPtr ptr;
71  Child c;
72  ptr = &c;
73 
74  // Make sure casting to base returns null. This may work in some trivial
75  // cases, but allowing down-casting in AnyPtr could break if, for example,
76  // multiple inheretance is being used.
77  EXPECT_EQ(nullptr, ptr.get<Base>());
78 
79  // Getting the pointer as the child type should work.
80  EXPECT_EQ(&c, ptr.get<Child>());
81 
82  // Make sure accessing as base works if we store the pointer as the base
83  // class.
84  ptr = static_cast<Base*>(&c);
85  EXPECT_EQ(&c, ptr.get<Base>());
86  EXPECT_EQ(nullptr, ptr.get<Child>());
87 }
88 
89 struct Destructable {
90  ~Destructable() { *destroyed = true; }
91 
92  bool* const destroyed;
93 };
94 
95 TEST(UniqueAnyPtrTest, SetGetAndDestroy) {
96  bool destroyed = false;
97  UniqueAnyPtr ptr;
98 
99  // Move constructable.
100  ptr =
101  UniqueAnyPtr{std::unique_ptr<Destructable>{new Destructable{&destroyed}}};
102  EXPECT_EQ(&destroyed, ptr.get<Destructable>()->destroyed);
103  EXPECT_EQ(nullptr, ptr.get<int>());
104  ASSERT_FALSE(destroyed);
105 
106  // Implicitly settable/constructable from nullptr.
107  ptr = nullptr;
108  EXPECT_TRUE(destroyed);
109 }
110 
111 TEST(UniqueAnyPtrTest, MoveConstruction) {
112  UniqueAnyPtr ptr1 = UniqueAnyPtr(std::unique_ptr<int>(new int(1)));
113  UniqueAnyPtr ptr2(std::move(ptr1));
114 
115  ASSERT_EQ(1, *ptr2.get<int>());
116 }
117 
118 } // namespace
119 } // namespace serving
120 } // namespace tensorflow