xref: /aosp_15_r20/external/tensorflow/tensorflow/core/platform/statusor_test.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2017 The TensorFlow Authors. 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 // Unit tests for StatusOr
17 
18 #include "tensorflow/core/platform/statusor.h"
19 
20 #include <memory>
21 #include <type_traits>
22 #include <utility>
23 
24 #include "tensorflow/core/lib/core/errors.h"
25 #include "tensorflow/core/platform/macros.h"
26 #include "tensorflow/core/platform/test.h"
27 #include "tensorflow/core/platform/test_benchmark.h"
28 
29 namespace tensorflow {
30 namespace {
31 
32 class Base1 {
33  public:
~Base1()34   virtual ~Base1() {}
35   int pad_;
36 };
37 
38 class Base2 {
39  public:
~Base2()40   virtual ~Base2() {}
41   int yetotherpad_;
42 };
43 
44 class Derived : public Base1, public Base2 {
45  public:
~Derived()46   ~Derived() override {}
47   int evenmorepad_;
48 };
49 
50 class CopyNoAssign {
51  public:
CopyNoAssign(int value)52   explicit CopyNoAssign(int value) : foo_(value) {}
CopyNoAssign(const CopyNoAssign & other)53   CopyNoAssign(const CopyNoAssign& other) : foo_(other.foo_) {}
54   int foo_;
55 
56  private:
57   const CopyNoAssign& operator=(const CopyNoAssign&);
58 };
59 
60 class NoDefaultConstructor {
61  public:
62   explicit NoDefaultConstructor(int foo);
63 };
64 
65 static_assert(!std::is_default_constructible<NoDefaultConstructor>(),
66               "Should not be default-constructible.");
67 
ReturnUniquePtr()68 StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {
69   // Uses implicit constructor from T&&
70   return std::unique_ptr<int>(new int(0));
71 }
72 
TEST(StatusOr,ElementType)73 TEST(StatusOr, ElementType) {
74   static_assert(std::is_same<StatusOr<int>::element_type, int>(), "");
75   static_assert(std::is_same<StatusOr<char>::element_type, char>(), "");
76 }
77 
TEST(StatusOr,NullPointerStatusOr)78 TEST(StatusOr, NullPointerStatusOr) {
79   // As a very special case, null-plain-pointer StatusOr used to be an
80   // error. Test that it no longer is.
81   StatusOr<int*> null_status(nullptr);
82   EXPECT_TRUE(null_status.ok());
83   EXPECT_EQ(null_status.ValueOrDie(), nullptr);
84 }
85 
TEST(StatusOr,TestNoDefaultConstructorInitialization)86 TEST(StatusOr, TestNoDefaultConstructorInitialization) {
87   // Explicitly initialize it with an error code.
88   StatusOr<NoDefaultConstructor> statusor(tensorflow::errors::Cancelled(""));
89   EXPECT_FALSE(statusor.ok());
90   EXPECT_EQ(statusor.status().code(), tensorflow::error::CANCELLED);
91 
92   // Default construction of StatusOr initializes it with an UNKNOWN error code.
93   StatusOr<NoDefaultConstructor> statusor2;
94   EXPECT_FALSE(statusor2.ok());
95   EXPECT_EQ(statusor2.status().code(), tensorflow::error::UNKNOWN);
96 }
97 
TEST(StatusOr,TestMoveOnlyInitialization)98 TEST(StatusOr, TestMoveOnlyInitialization) {
99   StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
100   ASSERT_TRUE(thing.ok());
101   EXPECT_EQ(0, *thing.ValueOrDie());
102   int* previous = thing.ValueOrDie().get();
103 
104   thing = ReturnUniquePtr();
105   EXPECT_TRUE(thing.ok());
106   EXPECT_EQ(0, *thing.ValueOrDie());
107   EXPECT_NE(previous, thing.ValueOrDie().get());
108 }
109 
TEST(StatusOr,TestMoveOnlyStatusCtr)110 TEST(StatusOr, TestMoveOnlyStatusCtr) {
111   StatusOr<std::unique_ptr<int>> thing(tensorflow::errors::Cancelled(""));
112   ASSERT_FALSE(thing.ok());
113 }
114 
TEST(StatusOr,TestMoveOnlyValueExtraction)115 TEST(StatusOr, TestMoveOnlyValueExtraction) {
116   StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
117   ASSERT_TRUE(thing.ok());
118   std::unique_ptr<int> ptr = std::move(thing).value();
119   EXPECT_EQ(0, *ptr);
120 
121   thing = std::move(ptr);
122   ptr = std::move(thing.ValueOrDie());
123   EXPECT_EQ(0, *ptr);
124 }
125 
TEST(StatusOr,TestMoveOnlyConversion)126 TEST(StatusOr, TestMoveOnlyConversion) {
127   StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
128   EXPECT_TRUE(const_thing.ok());
129   EXPECT_EQ(0, *const_thing.ValueOrDie());
130 
131   // Test rvalue converting assignment
132   const int* const_previous = const_thing.ValueOrDie().get();
133   const_thing = ReturnUniquePtr();
134   EXPECT_TRUE(const_thing.ok());
135   EXPECT_EQ(0, *const_thing.ValueOrDie());
136   EXPECT_NE(const_previous, const_thing.ValueOrDie().get());
137 }
138 
TEST(StatusOr,TestMoveOnlyVector)139 TEST(StatusOr, TestMoveOnlyVector) {
140   // Sanity check that StatusOr<MoveOnly> works in vector.
141   std::vector<StatusOr<std::unique_ptr<int>>> vec;
142   vec.push_back(ReturnUniquePtr());
143   vec.resize(2);
144   auto another_vec = std::move(vec);
145   EXPECT_EQ(0, *another_vec[0].ValueOrDie());
146   EXPECT_EQ(tensorflow::error::UNKNOWN, another_vec[1].status().code());
147 }
148 
TEST(StatusOr,TestMoveWithValuesAndErrors)149 TEST(StatusOr, TestMoveWithValuesAndErrors) {
150   StatusOr<std::string> status_or(std::string(1000, '0'));
151   StatusOr<std::string> value1(std::string(1000, '1'));
152   StatusOr<std::string> value2(std::string(1000, '2'));
153   StatusOr<std::string> error1(Status(tensorflow::error::UNKNOWN, "error1"));
154   StatusOr<std::string> error2(Status(tensorflow::error::UNKNOWN, "error2"));
155 
156   ASSERT_TRUE(status_or.ok());
157   EXPECT_EQ(std::string(1000, '0'), status_or.ValueOrDie());
158 
159   // Overwrite the value in status_or with another value.
160   status_or = std::move(value1);
161   ASSERT_TRUE(status_or.ok());
162   EXPECT_EQ(std::string(1000, '1'), status_or.ValueOrDie());
163 
164   // Overwrite the value in status_or with an error.
165   status_or = std::move(error1);
166   ASSERT_FALSE(status_or.ok());
167   EXPECT_EQ("error1", status_or.status().error_message());
168 
169   // Overwrite the error in status_or with another error.
170   status_or = std::move(error2);
171   ASSERT_FALSE(status_or.ok());
172   EXPECT_EQ("error2", status_or.status().error_message());
173 
174   // Overwrite the error with a value.
175   status_or = std::move(value2);
176   ASSERT_TRUE(status_or.ok());
177   EXPECT_EQ(std::string(1000, '2'), status_or.ValueOrDie());
178 }
179 
TEST(StatusOr,TestCopyWithValuesAndErrors)180 TEST(StatusOr, TestCopyWithValuesAndErrors) {
181   StatusOr<std::string> status_or(std::string(1000, '0'));
182   StatusOr<std::string> value1(std::string(1000, '1'));
183   StatusOr<std::string> value2(std::string(1000, '2'));
184   StatusOr<std::string> error1(Status(tensorflow::error::UNKNOWN, "error1"));
185   StatusOr<std::string> error2(Status(tensorflow::error::UNKNOWN, "error2"));
186 
187   ASSERT_TRUE(status_or.ok());
188   EXPECT_EQ(std::string(1000, '0'), status_or.ValueOrDie());
189 
190   // Overwrite the value in status_or with another value.
191   status_or = value1;
192   ASSERT_TRUE(status_or.ok());
193   EXPECT_EQ(std::string(1000, '1'), status_or.ValueOrDie());
194 
195   // Overwrite the value in status_or with an error.
196   status_or = error1;
197   ASSERT_FALSE(status_or.ok());
198   EXPECT_EQ("error1", status_or.status().error_message());
199 
200   // Overwrite the error in status_or with another error.
201   status_or = error2;
202   ASSERT_FALSE(status_or.ok());
203   EXPECT_EQ("error2", status_or.status().error_message());
204 
205   // Overwrite the error with a value.
206   status_or = value2;
207   ASSERT_TRUE(status_or.ok());
208   EXPECT_EQ(std::string(1000, '2'), status_or.ValueOrDie());
209 
210   // Verify original values unchanged.
211   EXPECT_EQ(std::string(1000, '1'), value1.ValueOrDie());
212   EXPECT_EQ("error1", error1.status().error_message());
213   EXPECT_EQ("error2", error2.status().error_message());
214   EXPECT_EQ(std::string(1000, '2'), value2.ValueOrDie());
215 }
216 
TEST(StatusOr,TestDefaultCtor)217 TEST(StatusOr, TestDefaultCtor) {
218   StatusOr<int> thing;
219   EXPECT_FALSE(thing.ok());
220   EXPECT_EQ(thing.status().code(), tensorflow::error::UNKNOWN);
221 }
222 
TEST(StatusOrDeathTest,TestDefaultCtorValue)223 TEST(StatusOrDeathTest, TestDefaultCtorValue) {
224   StatusOr<int> thing;
225   EXPECT_DEATH(thing.ValueOrDie(), "");
226 
227   const StatusOr<int> thing2;
228   EXPECT_DEATH(thing.ValueOrDie(), "");
229 }
230 
TEST(StatusOr,TestStatusCtor)231 TEST(StatusOr, TestStatusCtor) {
232   StatusOr<int> thing(Status(tensorflow::error::CANCELLED, ""));
233   EXPECT_FALSE(thing.ok());
234   EXPECT_EQ(thing.status().code(), tensorflow::error::CANCELLED);
235 }
236 
TEST(StatusOr,TestValueCtor)237 TEST(StatusOr, TestValueCtor) {
238   const int kI = 4;
239   const StatusOr<int> thing(kI);
240   EXPECT_TRUE(thing.ok());
241   EXPECT_EQ(kI, thing.ValueOrDie());
242 }
243 
TEST(StatusOr,TestCopyCtorStatusOk)244 TEST(StatusOr, TestCopyCtorStatusOk) {
245   const int kI = 4;
246   const StatusOr<int> original(kI);
247   const StatusOr<int> copy(original);
248   EXPECT_EQ(copy.status(), original.status());
249   EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
250 }
251 
TEST(StatusOr,TestCopyCtorStatusNotOk)252 TEST(StatusOr, TestCopyCtorStatusNotOk) {
253   StatusOr<int> original(Status(tensorflow::error::CANCELLED, ""));
254   StatusOr<int> copy(original);
255   EXPECT_EQ(copy.status(), original.status());
256 }
257 
TEST(StatusOr,TestCopyCtorNonAssignable)258 TEST(StatusOr, TestCopyCtorNonAssignable) {
259   const int kI = 4;
260   CopyNoAssign value(kI);
261   StatusOr<CopyNoAssign> original(value);
262   StatusOr<CopyNoAssign> copy(original);
263   EXPECT_EQ(copy.status(), original.status());
264   EXPECT_EQ(original.ValueOrDie().foo_, copy.ValueOrDie().foo_);
265 }
266 
TEST(StatusOr,TestCopyCtorStatusOKConverting)267 TEST(StatusOr, TestCopyCtorStatusOKConverting) {
268   const int kI = 4;
269   StatusOr<int> original(kI);
270   StatusOr<double> copy(original);
271   EXPECT_EQ(copy.status(), original.status());
272   EXPECT_DOUBLE_EQ(original.ValueOrDie(), copy.ValueOrDie());
273 }
274 
TEST(StatusOr,TestCopyCtorStatusNotOkConverting)275 TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
276   StatusOr<int> original(Status(tensorflow::error::CANCELLED, ""));
277   StatusOr<double> copy(original);
278   EXPECT_EQ(copy.status(), original.status());
279 }
280 
TEST(StatusOr,TestAssignmentStatusOk)281 TEST(StatusOr, TestAssignmentStatusOk) {
282   const int kI = 4;
283   StatusOr<int> source(kI);
284   StatusOr<int> target;
285   target = source;
286   EXPECT_EQ(target.status(), source.status());
287   EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
288 }
289 
TEST(StatusOr,TestAssignmentStatusNotOk)290 TEST(StatusOr, TestAssignmentStatusNotOk) {
291   StatusOr<int> source(Status(tensorflow::error::CANCELLED, ""));
292   StatusOr<int> target;
293   target = source;
294   EXPECT_EQ(target.status(), source.status());
295 }
296 
TEST(StatusOr,TestStatus)297 TEST(StatusOr, TestStatus) {
298   StatusOr<int> good(4);
299   EXPECT_TRUE(good.ok());
300   StatusOr<int> bad(Status(tensorflow::error::CANCELLED, ""));
301   EXPECT_FALSE(bad.ok());
302   EXPECT_EQ(bad.status(), Status(tensorflow::error::CANCELLED, ""));
303 }
304 
TEST(StatusOr,TestValue)305 TEST(StatusOr, TestValue) {
306   const int kI = 4;
307   StatusOr<int> thing(kI);
308   EXPECT_EQ(kI, thing.ValueOrDie());
309 }
310 
TEST(StatusOr,TestValueConst)311 TEST(StatusOr, TestValueConst) {
312   const int kI = 4;
313   const StatusOr<int> thing(kI);
314   EXPECT_EQ(kI, thing.ValueOrDie());
315 }
316 
TEST(StatusOrDeathTest,TestValueNotOk)317 TEST(StatusOrDeathTest, TestValueNotOk) {
318   StatusOr<int> thing(Status(tensorflow::error::CANCELLED, "cancelled"));
319   EXPECT_DEATH(thing.ValueOrDie(), "cancelled");
320 }
321 
TEST(StatusOrDeathTest,TestValueNotOkConst)322 TEST(StatusOrDeathTest, TestValueNotOkConst) {
323   const StatusOr<int> thing(Status(tensorflow::error::UNKNOWN, ""));
324   EXPECT_DEATH(thing.ValueOrDie(), "");
325 }
326 
TEST(StatusOr,TestPointerDefaultCtor)327 TEST(StatusOr, TestPointerDefaultCtor) {
328   StatusOr<int*> thing;
329   EXPECT_FALSE(thing.ok());
330   EXPECT_EQ(thing.status().code(), tensorflow::error::UNKNOWN);
331 }
332 
TEST(StatusOrDeathTest,TestPointerDefaultCtorValue)333 TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {
334   StatusOr<int*> thing;
335   EXPECT_DEATH(thing.ValueOrDie(), "");
336 }
337 
TEST(StatusOr,TestPointerStatusCtor)338 TEST(StatusOr, TestPointerStatusCtor) {
339   StatusOr<int*> thing(Status(tensorflow::error::CANCELLED, ""));
340   EXPECT_FALSE(thing.ok());
341   EXPECT_EQ(thing.status(), Status(tensorflow::error::CANCELLED, ""));
342 }
343 
TEST(StatusOr,TestPointerValueCtor)344 TEST(StatusOr, TestPointerValueCtor) {
345   const int kI = 4;
346   StatusOr<const int*> thing(&kI);
347   EXPECT_TRUE(thing.ok());
348   EXPECT_EQ(&kI, thing.ValueOrDie());
349 }
350 
TEST(StatusOr,TestPointerCopyCtorStatusOk)351 TEST(StatusOr, TestPointerCopyCtorStatusOk) {
352   const int kI = 0;
353   StatusOr<const int*> original(&kI);
354   StatusOr<const int*> copy(original);
355   EXPECT_EQ(copy.status(), original.status());
356   EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
357 }
358 
TEST(StatusOr,TestPointerCopyCtorStatusNotOk)359 TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
360   StatusOr<int*> original(Status(tensorflow::error::CANCELLED, ""));
361   StatusOr<int*> copy(original);
362   EXPECT_EQ(copy.status(), original.status());
363 }
364 
TEST(StatusOr,TestPointerCopyCtorStatusOKConverting)365 TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
366   Derived derived;
367   StatusOr<Derived*> original(&derived);
368   StatusOr<Base2*> copy(original);
369   EXPECT_EQ(copy.status(), original.status());
370   EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()),
371             copy.ValueOrDie());
372 }
373 
TEST(StatusOr,TestPointerCopyCtorStatusNotOkConverting)374 TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
375   StatusOr<Derived*> original(Status(tensorflow::error::CANCELLED, ""));
376   StatusOr<Base2*> copy(original);
377   EXPECT_EQ(copy.status(), original.status());
378 }
379 
TEST(StatusOr,TestPointerAssignmentStatusOk)380 TEST(StatusOr, TestPointerAssignmentStatusOk) {
381   const int kI = 0;
382   StatusOr<const int*> source(&kI);
383   StatusOr<const int*> target;
384   target = source;
385   EXPECT_EQ(target.status(), source.status());
386   EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
387 }
388 
TEST(StatusOr,TestPointerAssignmentStatusNotOk)389 TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
390   StatusOr<int*> source(Status(tensorflow::error::CANCELLED, ""));
391   StatusOr<int*> target;
392   target = source;
393   EXPECT_EQ(target.status(), source.status());
394 }
395 
TEST(StatusOr,TestPointerStatus)396 TEST(StatusOr, TestPointerStatus) {
397   const int kI = 0;
398   StatusOr<const int*> good(&kI);
399   EXPECT_TRUE(good.ok());
400   StatusOr<const int*> bad(Status(tensorflow::error::CANCELLED, ""));
401   EXPECT_EQ(bad.status(), Status(tensorflow::error::CANCELLED, ""));
402 }
403 
TEST(StatusOr,TestPointerValue)404 TEST(StatusOr, TestPointerValue) {
405   const int kI = 0;
406   StatusOr<const int*> thing(&kI);
407   EXPECT_EQ(&kI, thing.ValueOrDie());
408 }
409 
TEST(StatusOr,TestPointerValueConst)410 TEST(StatusOr, TestPointerValueConst) {
411   const int kI = 0;
412   const StatusOr<const int*> thing(&kI);
413   EXPECT_EQ(&kI, thing.ValueOrDie());
414 }
415 
TEST(StatusOr,TestArrowOperator)416 TEST(StatusOr, TestArrowOperator) {
417   StatusOr<std::unique_ptr<int>> uptr = ReturnUniquePtr();
418   EXPECT_EQ(*uptr->get(), 0);
419 }
420 
TEST(StatusOr,TestArrowOperatorNotOk)421 TEST(StatusOr, TestArrowOperatorNotOk) {
422   StatusOr<Base1> error(Status(tensorflow::error::CANCELLED, "cancelled"));
423   EXPECT_DEATH(error->pad_++, "cancelled");
424 }
425 
TEST(StatusOr,TestStarOperator)426 TEST(StatusOr, TestStarOperator) {
427   StatusOr<std::unique_ptr<int>> uptr = ReturnUniquePtr();
428   EXPECT_EQ(**uptr, 0);
429 }
430 
TEST(StatusOr,TestStarOperatorDeath)431 TEST(StatusOr, TestStarOperatorDeath) {
432   StatusOr<Base1> error(Status(tensorflow::error::CANCELLED, "cancelled"));
433   EXPECT_DEATH(*error, "cancelled");
434 }
435 
436 // NOTE(tucker): StatusOr does not support this kind
437 // of resize op.
438 // TEST(StatusOr, StatusOrVectorOfUniquePointerCanResize) {
439 //   using EvilType = std::vector<std::unique_ptr<int>>;
440 //   static_assert(std::is_copy_constructible<EvilType>::value, "");
441 //   std::vector<StatusOr<EvilType>> v(5);
442 //   v.reserve(v.capacity() + 10);
443 // }
444 
TEST(StatusOrDeathTest,TestPointerValueNotOk)445 TEST(StatusOrDeathTest, TestPointerValueNotOk) {
446   StatusOr<int*> thing(Status(tensorflow::error::CANCELLED, "cancelled"));
447   EXPECT_DEATH(thing.ValueOrDie(), "cancelled");
448 }
449 
TEST(StatusOrDeathTest,TestPointerValueNotOkConst)450 TEST(StatusOrDeathTest, TestPointerValueNotOkConst) {
451   const StatusOr<int*> thing(Status(tensorflow::error::CANCELLED, "cancelled"));
452   EXPECT_DEATH(thing.ValueOrDie(), "cancelled");
453 }
454 
MakeStatus()455 static StatusOr<int> MakeStatus() { return 100; }
456 // A factory to help us benchmark the various factory styles. All of
457 // the factory methods are marked as non-inlineable so as to more
458 // accurately simulate calling a factory for which you do not have
459 // visibility of implementation. Similarly, the value_ variable is
460 // marked volatile to prevent the compiler from getting too clever
461 // about detecting that the same value is used in all loop iterations.
462 template <typename T>
463 class BenchmarkFactory {
464  public:
465   // Construct a new factory. Allocate an object which will always
466   // be the result of the factory methods.
BenchmarkFactory()467   BenchmarkFactory() : value_(new T) {}
468 
469   // Destroy this factory, including the result value.
~BenchmarkFactory()470   ~BenchmarkFactory() { delete value_; }
471 
472   // A trivial factory that just returns the value. There is no status
473   // object that could be returned to encapsulate an error
TrivialFactory()474   T* TrivialFactory() TF_ATTRIBUTE_NOINLINE { return value_; }
475 
476   // A more sophisticated factory, which returns a status to indicate
477   // the result of the operation. The factory result is populated into
478   // the user provided pointer result.
ArgumentFactory(T ** result)479   Status ArgumentFactory(T** result) TF_ATTRIBUTE_NOINLINE {
480     *result = value_;
481     return OkStatus();
482   }
483 
ArgumentFactoryFail(T ** result)484   Status ArgumentFactoryFail(T** result) TF_ATTRIBUTE_NOINLINE {
485     *result = nullptr;
486     return Status(tensorflow::error::CANCELLED, "");
487   }
488 
ArgumentFactoryFailShortMsg(T ** result)489   Status ArgumentFactoryFailShortMsg(T** result) TF_ATTRIBUTE_NOINLINE {
490     *result = nullptr;
491     return Status(::tensorflow::error::INTERNAL, "");
492   }
493 
ArgumentFactoryFailLongMsg(T ** result)494   Status ArgumentFactoryFailLongMsg(T** result) TF_ATTRIBUTE_NOINLINE {
495     *result = nullptr;
496     return Status(::tensorflow::error::INTERNAL,
497                   "a big string of message junk that will never be read");
498   }
499 
500   // A factory that returns a StatusOr<T*>. If the factory operation
501   // is OK, then the StatusOr<T*> will hold a T*. Otherwise, it will
502   // hold a status explaining the error.
StatusOrFactory()503   StatusOr<T*> StatusOrFactory() TF_ATTRIBUTE_NOINLINE {
504     return static_cast<T*>(value_);
505   }
506 
StatusOrFactoryFail()507   StatusOr<T*> StatusOrFactoryFail() TF_ATTRIBUTE_NOINLINE {
508     return Status(tensorflow::error::CANCELLED, "");
509   }
510 
StatusOrFactoryFailShortMsg()511   StatusOr<T*> StatusOrFactoryFailShortMsg() TF_ATTRIBUTE_NOINLINE {
512     return Status(::tensorflow::error::INTERNAL, "");
513   }
514 
StatusOrFactoryFailLongMsg()515   StatusOr<T*> StatusOrFactoryFailLongMsg() TF_ATTRIBUTE_NOINLINE {
516     return Status(::tensorflow::error::INTERNAL,
517                   "a big string of message junk that will never be read");
518   }
519 
520  private:
521   T* volatile value_;
522   TF_DISALLOW_COPY_AND_ASSIGN(BenchmarkFactory);
523 };
524 
525 // A simple type we use with the factory.
526 class BenchmarkType {
527  public:
BenchmarkType()528   BenchmarkType() {}
~BenchmarkType()529   virtual ~BenchmarkType() {}
DoWork()530   virtual void DoWork() TF_ATTRIBUTE_NOINLINE {}
531 
532  private:
533   TF_DISALLOW_COPY_AND_ASSIGN(BenchmarkType);
534 };
535 
536 // Calibrate the amount of time spent just calling DoWork, since each of our
537 // tests will do this, we can subtract this out of benchmark results.
BM_CalibrateWorkLoop(::testing::benchmark::State & state)538 void BM_CalibrateWorkLoop(::testing::benchmark::State& state) {
539   BenchmarkFactory<BenchmarkType> factory;
540   BenchmarkType* result = factory.TrivialFactory();
541   for (auto s : state) {
542     if (result != nullptr) {
543       result->DoWork();
544     }
545   }
546 }
547 BENCHMARK(BM_CalibrateWorkLoop);
548 
549 // Measure the time taken to call into the factory, return the value,
550 // determine that it is OK, and invoke a trivial function.
BM_TrivialFactory(::testing::benchmark::State & state)551 void BM_TrivialFactory(::testing::benchmark::State& state) {
552   BenchmarkFactory<BenchmarkType> factory;
553   for (auto s : state) {
554     BenchmarkType* result = factory.TrivialFactory();
555     if (result != nullptr) {
556       result->DoWork();
557     }
558   }
559 }
560 BENCHMARK(BM_TrivialFactory);
561 
562 // Measure the time taken to call into the factory, providing an
563 // out-param for the result, evaluating the status result and the
564 // result pointer, and invoking the trivial function.
BM_ArgumentFactory(::testing::benchmark::State & state)565 void BM_ArgumentFactory(::testing::benchmark::State& state) {
566   BenchmarkFactory<BenchmarkType> factory;
567   for (auto s : state) {
568     BenchmarkType* result = nullptr;
569     Status status = factory.ArgumentFactory(&result);
570     if (status.ok() && result != nullptr) {
571       result->DoWork();
572     }
573   }
574 }
575 BENCHMARK(BM_ArgumentFactory);
576 
577 // Measure the time to use the StatusOr<T*> factory, evaluate the result,
578 // and invoke the trivial function.
BM_StatusOrFactory(::testing::benchmark::State & state)579 void BM_StatusOrFactory(::testing::benchmark::State& state) {
580   BenchmarkFactory<BenchmarkType> factory;
581   for (auto s : state) {
582     StatusOr<BenchmarkType*> result = factory.StatusOrFactory();
583     if (result.ok()) {
584       result.ValueOrDie()->DoWork();
585     }
586   }
587 }
588 BENCHMARK(BM_StatusOrFactory);
589 
590 // Measure the time taken to call into the factory, providing an
591 // out-param for the result, evaluating the status result and the
592 // result pointer, and invoking the trivial function.
BM_ArgumentFactoryFail(::testing::benchmark::State & state)593 void BM_ArgumentFactoryFail(::testing::benchmark::State& state) {
594   BenchmarkFactory<BenchmarkType> factory;
595   for (auto s : state) {
596     BenchmarkType* result = nullptr;
597     Status status = factory.ArgumentFactoryFail(&result);
598     if (status.ok() && result != nullptr) {
599       result->DoWork();
600     }
601   }
602 }
603 BENCHMARK(BM_ArgumentFactoryFail);
604 
605 // Measure the time to use the StatusOr<T*> factory, evaluate the result,
606 // and invoke the trivial function.
BM_StatusOrFactoryFail(::testing::benchmark::State & state)607 void BM_StatusOrFactoryFail(::testing::benchmark::State& state) {
608   BenchmarkFactory<BenchmarkType> factory;
609   for (auto s : state) {
610     StatusOr<BenchmarkType*> result = factory.StatusOrFactoryFail();
611     if (result.ok()) {
612       result.ValueOrDie()->DoWork();
613     }
614   }
615 }
616 BENCHMARK(BM_StatusOrFactoryFail);
617 
618 // Measure the time taken to call into the factory, providing an
619 // out-param for the result, evaluating the status result and the
620 // result pointer, and invoking the trivial function.
BM_ArgumentFactoryFailShortMsg(::testing::benchmark::State & state)621 void BM_ArgumentFactoryFailShortMsg(::testing::benchmark::State& state) {
622   BenchmarkFactory<BenchmarkType> factory;
623   for (auto s : state) {
624     BenchmarkType* result = nullptr;
625     Status status = factory.ArgumentFactoryFailShortMsg(&result);
626     if (status.ok() && result != nullptr) {
627       result->DoWork();
628     }
629   }
630 }
631 BENCHMARK(BM_ArgumentFactoryFailShortMsg);
632 
633 // Measure the time to use the StatusOr<T*> factory, evaluate the result,
634 // and invoke the trivial function.
BM_StatusOrFactoryFailShortMsg(::testing::benchmark::State & state)635 void BM_StatusOrFactoryFailShortMsg(::testing::benchmark::State& state) {
636   BenchmarkFactory<BenchmarkType> factory;
637   for (auto s : state) {
638     StatusOr<BenchmarkType*> result = factory.StatusOrFactoryFailShortMsg();
639     if (result.ok()) {
640       result.ValueOrDie()->DoWork();
641     }
642   }
643 }
644 BENCHMARK(BM_StatusOrFactoryFailShortMsg);
645 
646 // Measure the time taken to call into the factory, providing an
647 // out-param for the result, evaluating the status result and the
648 // result pointer, and invoking the trivial function.
BM_ArgumentFactoryFailLongMsg(::testing::benchmark::State & state)649 void BM_ArgumentFactoryFailLongMsg(::testing::benchmark::State& state) {
650   BenchmarkFactory<BenchmarkType> factory;
651   for (auto s : state) {
652     BenchmarkType* result = nullptr;
653     Status status = factory.ArgumentFactoryFailLongMsg(&result);
654     if (status.ok() && result != nullptr) {
655       result->DoWork();
656     }
657   }
658 }
659 BENCHMARK(BM_ArgumentFactoryFailLongMsg);
660 
661 // Measure the time to use the StatusOr<T*> factory, evaluate the result,
662 // and invoke the trivial function.
BM_StatusOrFactoryFailLongMsg(::testing::benchmark::State & state)663 void BM_StatusOrFactoryFailLongMsg(::testing::benchmark::State& state) {
664   BenchmarkFactory<BenchmarkType> factory;
665   for (auto s : state) {
666     StatusOr<BenchmarkType*> result = factory.StatusOrFactoryFailLongMsg();
667     if (result.ok()) {
668       result.ValueOrDie()->DoWork();
669     }
670   }
671 }
672 BENCHMARK(BM_StatusOrFactoryFailLongMsg);
673 
674 }  // namespace
675 }  // namespace tensorflow
676