TensorFlow Serving C++ API Documentation
observer_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/observer.h"
17 
18 #include <functional>
19 #include <memory>
20 
21 #include <gtest/gtest.h>
22 #include "tensorflow/core/kernels/batching_util/periodic_function.h"
23 #include "tensorflow/core/platform/env.h"
24 
25 namespace tensorflow {
26 namespace serving {
27 namespace {
28 
29 TEST(ObserverTest, Call) {
30  int num_calls = 0;
31  Observer<> observer([&]() { num_calls++; });
32  observer.Notifier()();
33  EXPECT_EQ(1, num_calls);
34 }
35 
36 TEST(ObserverTest, CallWithArg) {
37  Observer<int> observer([&](int arg) { EXPECT_EQ(1337, arg); });
38  observer.Notifier()(1337);
39 }
40 
41 TEST(ObserverTest, Orphan) {
42  int num_calls = 0;
43  std::function<void()> notifier;
44  {
45  Observer<> observer([&]() { num_calls++; });
46  notifier = observer.Notifier();
47  EXPECT_EQ(0, num_calls);
48  notifier();
49  EXPECT_EQ(1, num_calls);
50  }
51  notifier();
52  EXPECT_EQ(1, num_calls);
53 }
54 
55 TEST(ObserverTest, ObserverList) {
56  int num_calls = 0;
57  Observer<> observer([&]() { num_calls++; });
58  ObserverList<> observers;
59  for (int i = 0; i < 10; ++i) {
60  observers.Add(observer);
61  }
62  observers.Notify();
63  EXPECT_EQ(10, num_calls);
64 }
65 
66 TEST(ObserverTest, ObserverListWithOrphans) {
67  int num_calls = 0;
68  ObserverList<> observers;
69  for (int i = 0; i < 10; ++i) {
70  Observer<> observer([&]() { num_calls++; });
71  observers.Add(observer);
72  }
73  observers.Notify();
74 
75  // Everything is an orphan, so no calls.
76  EXPECT_EQ(0, num_calls);
77 }
78 
79 TEST(ObserverTest, Threaded) {
80  mutex mu;
81  int num_calls = 0;
82  auto observer =
83  std::unique_ptr<Observer<>>(new Observer<>([&mu, &num_calls]() {
84  mutex_lock l(mu);
85  ++num_calls;
86  }));
87  auto notifier = observer->Notifier();
88 
89  // Spawn a thread and wait for it to run a few times.
90  PeriodicFunction thread(notifier, 1000 /* 1 milliseconds */);
91  while (true) {
92  {
93  mutex_lock l(mu);
94  if (num_calls >= 10) {
95  break;
96  }
97  }
98  Env::Default()->SleepForMicroseconds(1000 /* 1 milliseconds */);
99  }
100 
101  // Tear down the observer and make sure it is never called again.
102  observer = nullptr;
103  int num_calls_snapshot;
104  {
105  mutex_lock l(mu);
106  num_calls_snapshot = num_calls;
107  }
108  Env::Default()->SleepForMicroseconds(100 * 1000 /* 100 milliseconds */);
109  {
110  mutex_lock l(mu);
111  EXPECT_EQ(num_calls_snapshot, num_calls);
112  }
113 }
114 
115 } // namespace
116 } // namespace serving
117 } // namespace tensorflow