• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2015 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 #include <string.h>
17 
18 #include <fstream>
19 #include <vector>
20 
21 #include "tensorflow/core/debug/debug_io_utils.h"
22 #include "tensorflow/core/debug/debug_node_key.h"
23 #include "tensorflow/core/framework/fake_input.h"
24 #include "tensorflow/core/framework/node_def_builder.h"
25 #include "tensorflow/core/framework/summary.pb.h"
26 #include "tensorflow/core/framework/tensor.h"
27 #include "tensorflow/core/framework/tensor_testutil.h"
28 #include "tensorflow/core/framework/types.h"
29 #include "tensorflow/core/framework/types.pb.h"
30 #include "tensorflow/core/kernels/ops_testutil.h"
31 #include "tensorflow/core/kernels/ops_util.h"
32 #include "tensorflow/core/lib/core/status_test_util.h"
33 #include "tensorflow/core/lib/io/path.h"
34 #include "tensorflow/core/lib/strings/strcat.h"
35 #include "tensorflow/core/platform/env.h"
36 #include "tensorflow/core/platform/test.h"
37 #include "tensorflow/core/util/event.pb.h"
38 
39 namespace tensorflow {
40 
41 class DebugIdentityOpTest : public OpsTestBase {
42  protected:
Init(DataType input_type,const std::vector<string> & debug_urls)43   Status Init(DataType input_type, const std::vector<string>& debug_urls) {
44     env_ = Env::Default();
45 
46     TF_CHECK_OK(NodeDefBuilder("op", "DebugIdentity")
47                     .Input(FakeInput(input_type))
48                     .Attr("tensor_name", "FakeTensor:0")
49                     .Attr("debug_urls", debug_urls)
50                     .Finalize(node_def()));
51     return InitOp();
52   }
53 
Init(DataType input_type)54   Status Init(DataType input_type) {
55     std::vector<string> empty_debug_urls;
56     return Init(input_type, empty_debug_urls);
57   }
58 
59   Env* env_;
60 };
61 
TEST_F(DebugIdentityOpTest,Int32Success_6)62 TEST_F(DebugIdentityOpTest, Int32Success_6) {
63   TF_ASSERT_OK(Init(DT_INT32));
64   AddInputFromArray<int32>(TensorShape({6}), {1, 2, 3, 4, 5, 6});
65   TF_ASSERT_OK(RunOpKernel());
66   Tensor expected(allocator(), DT_INT32, TensorShape({6}));
67   test::FillValues<int32>(&expected, {1, 2, 3, 4, 5, 6});
68   // Verify the identity output
69   test::ExpectTensorEqual<int32>(expected, *GetOutput(0));
70 }
71 
TEST_F(DebugIdentityOpTest,Int32Success_6_FileURLs)72 TEST_F(DebugIdentityOpTest, Int32Success_6_FileURLs) {
73   const int kNumDumpDirs = 3;
74 
75   const string tmp_dir = testing::TmpDir();
76 
77   std::vector<string> dump_roots;
78   std::vector<string> debug_urls;
79   for (int i = 0; i < kNumDumpDirs; ++i) {
80     const string dump_root = strings::StrCat(tmp_dir, "_", i);
81     dump_roots.push_back(dump_root);
82 
83     debug_urls.push_back(strings::StrCat("file://", dump_root));
84   }
85 
86   uint64 wall_time = Env::Default()->NowMicros();
87 
88   TF_ASSERT_OK(Init(DT_INT32, debug_urls));
89   AddInputFromArray<int32>(TensorShape({6}), {1, 2, 3, 4, 5, 6});
90   TF_ASSERT_OK(RunOpKernel());
91   Tensor expected(allocator(), DT_INT32, TensorShape({6}));
92   test::FillValues<int32>(&expected, {1, 2, 3, 4, 5, 6});
93   // Verify the identity output
94   test::ExpectTensorEqual<int32>(expected, *GetOutput(0));
95 
96   for (int i = 0; i < kNumDumpDirs; ++i) {
97     ASSERT_TRUE(env_->FileExists(dump_roots[i]).ok());
98     ASSERT_TRUE(env_->IsDirectory(dump_roots[i]).ok());
99 
100     std::vector<string> device_roots;
101     FileSystem* fs = nullptr;
102     TF_ASSERT_OK(Env::Default()->GetFileSystemForFile(dump_roots[i], &fs));
103     std::vector<string> children;
104     TF_ASSERT_OK(fs->GetChildren(dump_roots[i], &children));
105 
106     const string kDeviceDirPrefix = strings::StrCat(
107         DebugNodeKey::kMetadataFilePrefix, DebugNodeKey::kDeviceTag);
108     for (const string child : children) {
109       if (!strncmp(child.c_str(), kDeviceDirPrefix.c_str(),
110                    kDeviceDirPrefix.size())) {
111         device_roots.push_back(io::JoinPath(dump_roots[i], child));
112       }
113     }
114     ASSERT_EQ(1, device_roots.size());
115 
116     const string& device_root = device_roots[0];
117     TF_ASSERT_OK(Env::Default()->GetFileSystemForFile(device_root, &fs));
118     TF_ASSERT_OK(fs->GetChildren(device_root, &children));
119 
120     int dump_files_found = 0;
121     for (const string child : children) {
122       dump_files_found++;
123 
124       // Try reading the file into a Event proto.
125       const string dump_file_path = io::JoinPath(device_root, child);
126       std::fstream ifs(dump_file_path, std::ios::in | std::ios::binary);
127       Event event;
128       event.ParseFromIstream(&ifs);
129       ifs.close();
130 
131       ASSERT_GE(event.wall_time(), wall_time);
132       ASSERT_EQ(1, event.summary().value().size());
133       ASSERT_EQ(strings::StrCat("FakeTensor", ":", 0, ":", "DebugIdentity"),
134                 event.summary().value(0).node_name());
135 
136       Tensor tensor_prime(DT_INT32);
137       ASSERT_TRUE(tensor_prime.FromProto(event.summary().value(0).tensor()));
138 
139       // Verify tensor shape and value from the dump file.
140       ASSERT_EQ(TensorShape({6}), tensor_prime.shape());
141 
142       for (int j = 0; j < 6; ++j) {
143         ASSERT_EQ(j + 1, tensor_prime.flat<int32>()(j));
144       }
145     }
146 
147     ASSERT_EQ(1, dump_files_found);
148 
149     // Remove temporary dump directory and file.
150     int64_t undeleted_files = 0;
151     int64_t undeleted_dirs = 0;
152     ASSERT_TRUE(env_->DeleteRecursively(dump_roots[i], &undeleted_files,
153                                         &undeleted_dirs)
154                     .ok());
155     ASSERT_EQ(0, undeleted_files);
156     ASSERT_EQ(0, undeleted_dirs);
157   }
158 }
159 
TEST_F(DebugIdentityOpTest,Int32Success_2_3)160 TEST_F(DebugIdentityOpTest, Int32Success_2_3) {
161   TF_ASSERT_OK(Init(DT_INT32));
162   AddInputFromArray<int32>(TensorShape({2, 3}), {1, 2, 3, 4, 5, 6});
163   TF_ASSERT_OK(RunOpKernel());
164   Tensor expected(allocator(), DT_INT32, TensorShape({2, 3}));
165   test::FillValues<int32>(&expected, {1, 2, 3, 4, 5, 6});
166   test::ExpectTensorEqual<int32>(expected, *GetOutput(0));
167 }
168 
TEST_F(DebugIdentityOpTest,StringSuccess)169 TEST_F(DebugIdentityOpTest, StringSuccess) {
170   TF_ASSERT_OK(Init(DT_STRING));
171   AddInputFromArray<tstring>(TensorShape({6}), {"A", "b", "C", "d", "E", "f"});
172   TF_ASSERT_OK(RunOpKernel());
173   Tensor expected(allocator(), DT_STRING, TensorShape({6}));
174   test::FillValues<tstring>(&expected, {"A", "b", "C", "d", "E", "f"});
175   test::ExpectTensorEqual<tstring>(expected, *GetOutput(0));
176 }
177 
178 // Tests for DebugNanCountOp
179 class DebugNanCountOpTest : public OpsTestBase {
180  protected:
Init(DataType input_type)181   Status Init(DataType input_type) {
182     TF_CHECK_OK(NodeDefBuilder("op", "DebugNanCount")
183                     .Input(FakeInput(input_type))
184                     .Attr("tensor_name", "FakeTensor:0")
185                     .Finalize(node_def()));
186     return InitOp();
187   }
188 };
189 
TEST_F(DebugNanCountOpTest,Float_has_NaNs)190 TEST_F(DebugNanCountOpTest, Float_has_NaNs) {
191   TF_ASSERT_OK(Init(DT_FLOAT));
192   AddInputFromArray<float>(TensorShape({6}),
193                            {1.1, std::numeric_limits<float>::quiet_NaN(), 3.3,
194                             std::numeric_limits<float>::quiet_NaN(),
195                             std::numeric_limits<float>::quiet_NaN(), 6.6});
196   TF_ASSERT_OK(RunOpKernel());
197 
198   // Verify the NaN-count debug signal
199   Tensor expected_nan_count(allocator(), DT_INT64, TensorShape({1}));
200   test::FillValues<int64>(&expected_nan_count, {3});
201   test::ExpectTensorEqual<int64>(expected_nan_count, *GetOutput(0));
202 }
203 
TEST_F(DebugNanCountOpTest,Float_no_NaNs)204 TEST_F(DebugNanCountOpTest, Float_no_NaNs) {
205   TF_ASSERT_OK(Init(DT_FLOAT));
206   AddInputFromArray<float>(
207       TensorShape({6}),
208       {1.1, 2.2, 3.3, std::numeric_limits<float>::infinity(), 5.5, 6.6});
209   TF_ASSERT_OK(RunOpKernel());
210 
211   Tensor expected_nan_count(allocator(), DT_INT64, TensorShape({1}));
212   test::FillValues<int64>(&expected_nan_count, {0});
213   test::ExpectTensorEqual<int64>(expected_nan_count, *GetOutput(0));
214 }
215 
TEST_F(DebugNanCountOpTest,Double_has_NaNs)216 TEST_F(DebugNanCountOpTest, Double_has_NaNs) {
217   TF_ASSERT_OK(Init(DT_DOUBLE));
218   AddInputFromArray<double>(TensorShape({6}),
219                             {1.1, std::numeric_limits<double>::quiet_NaN(), 3.3,
220                              std::numeric_limits<double>::quiet_NaN(),
221                              std::numeric_limits<double>::quiet_NaN(), 6.6});
222   TF_ASSERT_OK(RunOpKernel());
223 
224   Tensor expected_nan_count(allocator(), DT_INT64, TensorShape({1}));
225   test::FillValues<int64>(&expected_nan_count, {3});
226   test::ExpectTensorEqual<int64>(expected_nan_count, *GetOutput(0));
227 }
228 
TEST_F(DebugNanCountOpTest,Double_no_NaNs)229 TEST_F(DebugNanCountOpTest, Double_no_NaNs) {
230   TF_ASSERT_OK(Init(DT_DOUBLE));
231   AddInputFromArray<double>(
232       TensorShape({6}),
233       {1.1, 2.2, 3.3, std::numeric_limits<double>::infinity(), 5.5, 6.6});
234   TF_ASSERT_OK(RunOpKernel());
235 
236   Tensor expected_nan_count(allocator(), DT_INT64, TensorShape({1}));
237   test::FillValues<int64>(&expected_nan_count, {0});
238   test::ExpectTensorEqual<int64>(expected_nan_count, *GetOutput(0));
239 }
240 
241 // Tests for DebugNumericSummaryOp
242 class DebugNumericSummaryOpTest : public OpsTestBase {
243  protected:
Init(DataType input_type)244   Status Init(DataType input_type) {
245     TF_CHECK_OK(NodeDefBuilder("op", "DebugNumericSummary")
246                     .Input(FakeInput(input_type))
247                     .Attr("tensor_name", "FakeTensor:0")
248                     .Finalize(node_def()));
249     return InitOp();
250   }
251 
InitGated(DataType input_type,const std::vector<string> & debug_urls)252   Status InitGated(DataType input_type, const std::vector<string>& debug_urls) {
253     TF_CHECK_OK(NodeDefBuilder("op", "DebugNumericSummary")
254                     .Input(FakeInput(input_type))
255                     .Attr("tensor_name", "FakeTensor:0")
256                     .Attr("gated_grpc", true)
257                     .Attr("debug_urls", debug_urls)
258                     .Finalize(node_def()));
259     return InitOp();
260   }
261 
262 #if defined(PLATFORM_GOOGLE)
ClearEnabledWatchKeys()263   void ClearEnabledWatchKeys() { DebugGrpcIO::ClearEnabledWatchKeys(); }
264 #endif
265 };
266 
TEST_F(DebugNumericSummaryOpTest,Float_full_house)267 TEST_F(DebugNumericSummaryOpTest, Float_full_house) {
268   TF_ASSERT_OK(Init(DT_FLOAT));
269   AddInputFromArray<float>(
270       TensorShape({18}),
271       {std::numeric_limits<float>::quiet_NaN(),
272        std::numeric_limits<float>::quiet_NaN(), 0.0f, 0.0f, 0.0f, -1.0f, -3.0f,
273        3.0f, 7.0f, -std::numeric_limits<float>::infinity(),
274        -std::numeric_limits<float>::infinity(),
275        std::numeric_limits<float>::infinity(),
276        std::numeric_limits<float>::infinity(),
277        std::numeric_limits<float>::infinity(),
278        std::numeric_limits<float>::infinity(),
279        std::numeric_limits<float>::infinity(),
280        std::numeric_limits<float>::quiet_NaN(),
281        std::numeric_limits<float>::quiet_NaN()});
282   TF_ASSERT_OK(RunOpKernel());
283 
284   Tensor expected(allocator(), DT_DOUBLE, TensorShape({15}));
285   test::FillValues<double>(
286       &expected,
287       {1.0,            // Is initialized.
288        18.0,           // Total element count.
289        4.0,            // nan count.
290        2.0,            // -inf count.
291        2.0,            // negative number count (excluding -inf).
292        3.0,            // zero count.
293        2.0,            // positive number count (excluding +inf).
294        5.0,            // +inf count.
295        -3.0,           // minimum of non-inf and non-nan elements.
296        7.0,            // maximum of non-inf and non-nan elements.
297        0.85714285714,  // mean of non-inf and non-nan elements.
298        8.97959183673,  // variance of non-inf and non-nan elements.
299        static_cast<double>(DT_FLOAT),  // dtype.
300        1.0,                            // Number of dimensions.
301        18.0});                         // Dimension size.
302 
303   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
304 }
305 
TEST_F(DebugNumericSummaryOpTest,Double_full_house)306 TEST_F(DebugNumericSummaryOpTest, Double_full_house) {
307   TF_ASSERT_OK(Init(DT_DOUBLE));
308   AddInputFromArray<double>(
309       TensorShape({18}),
310       {std::numeric_limits<double>::quiet_NaN(),
311        std::numeric_limits<double>::quiet_NaN(), 0.0, 0.0, 0.0, -1.0, -3.0, 3.0,
312        7.0, -std::numeric_limits<double>::infinity(),
313        -std::numeric_limits<double>::infinity(),
314        std::numeric_limits<double>::infinity(),
315        std::numeric_limits<double>::infinity(),
316        std::numeric_limits<double>::infinity(),
317        std::numeric_limits<double>::infinity(),
318        std::numeric_limits<double>::infinity(),
319        std::numeric_limits<double>::quiet_NaN(),
320        std::numeric_limits<double>::quiet_NaN()});
321   TF_ASSERT_OK(RunOpKernel());
322 
323   Tensor expected(allocator(), DT_DOUBLE, TensorShape({15}));
324   test::FillValues<double>(
325       &expected,
326       {1.0,            // Is initialized.
327        18.0,           // Total element count.
328        4.0,            // nan count.
329        2.0,            // -inf count.
330        2.0,            // negative count (excluding -inf).
331        3.0,            // zero count.
332        2.0,            // positive count (excluding +inf).
333        5.0,            // +inf count.
334        -3.0,           // minimum of non-inf and non-nan elements.
335        7.0,            // maximum of non-inf and non-nan elements.
336        0.85714285714,  // mean of non-inf and non-nan elements.
337        8.97959183673,  // variance of non-inf and non-nan elements.
338        static_cast<double>(DT_DOUBLE),  // dtype.
339        1.0,                             // Number of dimensions.
340        18.0});                          // Dimension size.
341 
342   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
343 }
344 
TEST_F(DebugNumericSummaryOpTest,Float_only_valid_values)345 TEST_F(DebugNumericSummaryOpTest, Float_only_valid_values) {
346   TF_ASSERT_OK(Init(DT_FLOAT));
347   AddInputFromArray<float>(TensorShape({2, 3}),
348                            {0.0f, 0.0f, -1.0f, 3.0f, 3.0f, 7.0f});
349   TF_ASSERT_OK(RunOpKernel());
350 
351   Tensor expected(allocator(), DT_DOUBLE, TensorShape({16}));
352   test::FillValues<double>(
353       &expected,
354       {1.0,            // Is initialized.
355        6.0,            // Total element count.
356        0.0,            // nan count.
357        0.0,            // -inf count.
358        1.0,            // negative count (excluding -inf).
359        2.0,            // zero count.
360        3.0,            // positive count (excluding +inf).
361        0.0,            // +inf count.
362        -1.0,           // minimum of non-inf and non-nan elements.
363        7.0,            // maximum of non-inf and non-nan elements.
364        2.0,            // mean of non-inf and non-nan elements.
365        7.33333333333,  // variance of non-inf and non-nan elements.
366        static_cast<double>(DT_FLOAT),  // dtype
367        2.0,                            // Number of dimensions.
368        2.0, 3.0});                     // Dimension sizes.
369 
370   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
371 }
372 
TEST_F(DebugNumericSummaryOpTest,Float_all_Inf_or_NaN)373 TEST_F(DebugNumericSummaryOpTest, Float_all_Inf_or_NaN) {
374   TF_ASSERT_OK(Init(DT_FLOAT));
375   AddInputFromArray<float>(TensorShape({3, 3}),
376                            {std::numeric_limits<float>::quiet_NaN(),
377                             std::numeric_limits<float>::quiet_NaN(),
378                             -std::numeric_limits<float>::infinity(),
379                             -std::numeric_limits<float>::infinity(),
380                             std::numeric_limits<float>::infinity(),
381                             std::numeric_limits<float>::infinity(),
382                             std::numeric_limits<float>::infinity(),
383                             std::numeric_limits<float>::quiet_NaN(),
384                             std::numeric_limits<float>::quiet_NaN()});
385   TF_ASSERT_OK(RunOpKernel());
386 
387   Tensor output_tensor = *GetOutput(0);
388   const double* output = output_tensor.template flat<double>().data();
389 
390   // Use ASSERT_NEAR below because test::ExpectTensorNear does not work with
391   // NaNs.
392   ASSERT_NEAR(1.0, output[0], 1e-8);  // Is initialized.
393   ASSERT_NEAR(9.0, output[1], 1e-8);  // Total element count.
394   ASSERT_NEAR(4.0, output[2], 1e-8);  // nan count.
395   ASSERT_NEAR(2.0, output[3], 1e-8);  // -inf count.
396   ASSERT_NEAR(0.0, output[4], 1e-8);  // negative count (excluding -inf).
397   ASSERT_NEAR(0.0, output[5], 1e-8);  // zero count.
398   ASSERT_NEAR(0.0, output[6], 1e-8);  // positive count (excluding +inf).
399   ASSERT_NEAR(3.0, output[7], 1e-8);  // +inf count.
400   // Due to the absence of any non-inf and non-nan values, the output of min,
401   // max, mean and var are all degenerate.
402   ASSERT_EQ(std::numeric_limits<float>::infinity(), output[8]);
403   ASSERT_EQ(-std::numeric_limits<float>::infinity(), output[9]);
404   ASSERT_TRUE(Eigen::numext::isnan(output[10]));
405   ASSERT_TRUE(Eigen::numext::isnan(output[11]));
406   ASSERT_EQ(static_cast<double>(DT_FLOAT), output[12]);
407   ASSERT_EQ(2.0, output[13]);
408   ASSERT_EQ(3.0, output[14]);
409   ASSERT_EQ(3.0, output[15]);
410 }
411 
TEST_F(DebugNumericSummaryOpTest,Many_dimensions_tensor_shape)412 TEST_F(DebugNumericSummaryOpTest, Many_dimensions_tensor_shape) {
413   TF_ASSERT_OK(Init(DT_FLOAT));
414   AddInputFromArray<float>(TensorShape({1, 3, 1, 1, 1, 1, 1}),
415                            {std::numeric_limits<float>::quiet_NaN(),
416                             -std::numeric_limits<float>::infinity(), -8.0});
417   TF_ASSERT_OK(RunOpKernel());
418 
419   Tensor expected(allocator(), DT_DOUBLE, TensorShape({21}));
420   test::FillValues<double>(&expected,
421                            {1.0,   // Is initialized.
422                             3.0,   // Total element count.
423                             1.0,   // nan count.
424                             1.0,   // -inf count.
425                             1.0,   // negative number count (excluding -inf).
426                             0.0,   // zero count.
427                             0.0,   // positive number count (excluding +inf).
428                             0.0,   // +inf count.
429                             -8.0,  // minimum of non-inf and non-nan elements.
430                             -8.0,  // maximum of non-inf and non-nan elements.
431                             -8.0,  // mean of non-inf and non-nan elements.
432                             0.0,   // variance of non-inf and non-nan elements.
433                             static_cast<double>(DT_FLOAT),  // dtype.
434                             7.0,  // Number of dimensions.
435                             1.0,
436                             3.0,
437                             1.0,
438                             1.0,
439                             1.0,
440                             1.0,
441                             1.0});  // Dimension sizes.
442 
443   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
444 }
445 
TEST_F(DebugNumericSummaryOpTest,Scalar_tensor_shape)446 TEST_F(DebugNumericSummaryOpTest, Scalar_tensor_shape) {
447   TF_ASSERT_OK(Init(DT_FLOAT));
448   AddInputFromArray<float>(TensorShape({}), {42.0});
449   TF_ASSERT_OK(RunOpKernel());
450 
451   Tensor expected(allocator(), DT_DOUBLE, TensorShape({14}));
452   test::FillValues<double>(&expected,
453                            {1.0,   // Is initialized.
454                             1.0,   // Total element count.
455                             0.0,   // nan count.
456                             0.0,   // -inf count.
457                             0.0,   // negative number count (excluding -inf).
458                             0.0,   // zero count.
459                             1.0,   // positive number count (excluding +inf).
460                             0.0,   // +inf count.
461                             42.0,  // minimum of non-inf and non-nan elements.
462                             42.0,  // maximum of non-inf and non-nan elements.
463                             42.0,  // mean of non-inf and non-nan elements.
464                             0.0,   // variance of non-inf and non-nan elements.
465                             static_cast<double>(DT_FLOAT),  // dtype.
466                             0.0});  // Number of dimensions.
467 
468   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
469 }
470 
TEST_F(DebugNumericSummaryOpTest,Int16Success)471 TEST_F(DebugNumericSummaryOpTest, Int16Success) {
472   TF_ASSERT_OK(Init(DT_INT16));
473   AddInputFromArray<int16>(TensorShape({4, 1}), {-1, -3, 3, 7});
474   TF_ASSERT_OK(RunOpKernel());
475 
476   Tensor expected(allocator(), DT_DOUBLE, TensorShape({16}));
477   test::FillValues<double>(&expected,
478                            {1.0,    // Is initialized.
479                             4.0,    // Total element count.
480                             0.0,    // nan count.
481                             0.0,    // -inf count.
482                             2.0,    // negative count (excluding -inf).
483                             0.0,    // zero count.
484                             2.0,    // positive count (excluding +inf).
485                             0.0,    // +inf count.
486                             -3.0,   // minimum of non-inf and non-nan elements.
487                             7.0,    // maximum of non-inf and non-nan elements.
488                             1.5,    // mean of non-inf and non-nan elements.
489                             14.75,  // variance of non-inf and non-nan elements.
490                             static_cast<double>(DT_INT16),  // dtype.
491                             2.0,         // Number of dimensions.
492                             4.0, 1.0});  // Dimension sizes.
493 
494   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
495 }
496 
TEST_F(DebugNumericSummaryOpTest,Int32Success)497 TEST_F(DebugNumericSummaryOpTest, Int32Success) {
498   TF_ASSERT_OK(Init(DT_INT32));
499   AddInputFromArray<int32>(TensorShape({2, 3}), {0, 0, -1, 3, 3, 7});
500   TF_ASSERT_OK(RunOpKernel());
501 
502   Tensor expected(allocator(), DT_DOUBLE, TensorShape({16}));
503   test::FillValues<double>(
504       &expected,
505       {1.0,            // Is initialized.
506        6.0,            // Total element count.
507        0.0,            // nan count.
508        0.0,            // -inf count.
509        1.0,            // negative count (excluding -inf).
510        2.0,            // zero count.
511        3.0,            // positive count (excluding +inf).
512        0.0,            // +inf count.
513        -1.0,           // minimum of non-inf and non-nan elements.
514        7.0,            // maximum of non-inf and non-nan elements.
515        2.0,            // mean of non-inf and non-nan elements.
516        7.33333333333,  // variance of non-inf and non-nan elements.
517        static_cast<double>(DT_INT32),  // dtype.
518        2.0,                            // Number of dimensions.
519        2.0, 3.0});                     // Dimension sizes.
520 
521   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
522 }
523 
TEST_F(DebugNumericSummaryOpTest,Int64Success)524 TEST_F(DebugNumericSummaryOpTest, Int64Success) {
525   TF_ASSERT_OK(Init(DT_INT64));
526   AddInputFromArray<int64>(TensorShape({2, 2, 2}), {0, 0, -1, 3, 3, 7, 0, 0});
527   TF_ASSERT_OK(RunOpKernel());
528 
529   Tensor expected(allocator(), DT_DOUBLE, TensorShape({17}));
530   test::FillValues<double>(&expected,
531                            {1.0,   // Is initialized.
532                             8.0,   // Total element count.
533                             0.0,   // nan count.
534                             0.0,   // -inf count.
535                             1.0,   // negative count (excluding -inf).
536                             4.0,   // zero count.
537                             3.0,   // positive count (excluding +inf).
538                             0.0,   // +inf count.
539                             -1.0,  // minimum of non-inf and non-nan elements.
540                             7.0,   // maximum of non-inf and non-nan elements.
541                             1.5,   // mean of non-inf and non-nan elements.
542                             6.25,  // variance of non-inf and non-nan elements.
543                             static_cast<double>(DT_INT64),  // dtype.
544                             3.0,              // Number of dimensions.
545                             2.0, 2.0, 2.0});  // Dimension sizes.
546 
547   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
548 }
549 
TEST_F(DebugNumericSummaryOpTest,UInt8Success)550 TEST_F(DebugNumericSummaryOpTest, UInt8Success) {
551   TF_ASSERT_OK(Init(DT_UINT8));
552   AddInputFromArray<uint8>(TensorShape({1, 5}), {0, 10, 30, 30, 70});
553   TF_ASSERT_OK(RunOpKernel());
554 
555   Tensor expected(allocator(), DT_DOUBLE, TensorShape({16}));
556   test::FillValues<double>(&expected,
557                            {1.0,    // Is initialized.
558                             5.0,    // Total element count.
559                             0.0,    // nan count.
560                             0.0,    // -inf count.
561                             0.0,    // negative count (excluding -inf).
562                             1.0,    // zero count.
563                             4.0,    // positive count (excluding +inf).
564                             0.0,    // +inf count.
565                             0.0,    // minimum of non-inf and non-nan elements.
566                             70.0,   // maximum of non-inf and non-nan elements.
567                             28.0,   // mean of non-inf and non-nan elements.
568                             576.0,  // variance of non-inf and non-nan elements.
569                             static_cast<double>(DT_UINT8),  // dtypes.
570                             2.0,         // Number of dimensions.
571                             1.0, 5.0});  // Dimension sizes.
572 
573   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
574 }
575 
TEST_F(DebugNumericSummaryOpTest,BoolSuccess)576 TEST_F(DebugNumericSummaryOpTest, BoolSuccess) {
577   TF_ASSERT_OK(Init(DT_BOOL));
578   AddInputFromArray<bool>(TensorShape({2, 3}),
579                           {false, false, true, true, true, false});
580   TF_ASSERT_OK(RunOpKernel());
581 
582   Tensor expected(allocator(), DT_DOUBLE, TensorShape({16}));
583   test::FillValues<double>(&expected,
584                            {1.0,   // Is initialized.
585                             6.0,   // Total element count.
586                             0.0,   // nan count.
587                             0.0,   // -inf count.
588                             0.0,   // negative count (excluding -inf).
589                             3.0,   // zero count.
590                             3.0,   // positive count (excluding +inf).
591                             0.0,   // +inf count.
592                             0.0,   // minimum of non-inf and non-nan elements.
593                             1.0,   // maximum of non-inf and non-nan elements.
594                             0.5,   // mean of non-inf and non-nan elements.
595                             0.25,  // variance of non-inf and non-nan elements.
596                             static_cast<double>(DT_BOOL),  // dtype.
597                             2.0,         // Number of dimensions.
598                             2.0, 3.0});  // Dimension sizes.
599 
600   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
601 }
602 
603 #if defined(PLATFORM_GOOGLE)
TEST_F(DebugNumericSummaryOpTest,DisabledDueToEmptyEnabledSet)604 TEST_F(DebugNumericSummaryOpTest, DisabledDueToEmptyEnabledSet) {
605   ClearEnabledWatchKeys();
606 
607   std::vector<string> debug_urls({"grpc://server:3333"});
608   TF_ASSERT_OK(InitGated(DT_FLOAT, debug_urls));
609   AddInputFromArray<float>(TensorShape({2, 2}), {1.0, 3.0, 3.0, 7.0});
610   TF_ASSERT_OK(RunOpKernel());
611 
612   Tensor expected_disabled(allocator(), DT_DOUBLE, TensorShape({0}));
613   test::ExpectTensorNear<double>(expected_disabled, *GetOutput(0), 1e-8);
614 }
615 
TEST_F(DebugNumericSummaryOpTest,DisabledDueToNonMatchingWatchKey)616 TEST_F(DebugNumericSummaryOpTest, DisabledDueToNonMatchingWatchKey) {
617   ClearEnabledWatchKeys();
618   DebugGrpcIO::SetDebugNodeKeyGrpcState(
619       "grpc://server:3333", "FakeTensor:1:DebugNumeriSummary",
620       EventReply::DebugOpStateChange::READ_ONLY);
621 
622   std::vector<string> debug_urls({"grpc://server:3333"});
623   TF_ASSERT_OK(InitGated(DT_FLOAT, debug_urls));
624   AddInputFromArray<float>(TensorShape({2, 2}), {1.0, 3.0, 3.0, 7.0});
625   TF_ASSERT_OK(RunOpKernel());
626 
627   Tensor expected_disabled(allocator(), DT_DOUBLE, TensorShape({0}));
628   test::ExpectTensorNear<double>(expected_disabled, *GetOutput(0), 1e-8);
629 }
630 #endif
631 
632 // Tests for DebugNumericSummaryOp
633 class DebugNumericSummaryOpCustomLowerBoundTest : public OpsTestBase {
634  protected:
Init(DataType input_type)635   Status Init(DataType input_type) {
636     TF_CHECK_OK(NodeDefBuilder("op", "DebugNumericSummary")
637                     .Input(FakeInput(input_type))
638                     .Attr("tensor_name", "FakeTensor:0")
639                     .Attr("lower_bound", -1.2f)
640                     .Finalize(node_def()));
641     return InitOp();
642   }
643 };
644 
TEST_F(DebugNumericSummaryOpCustomLowerBoundTest,Float_full_house)645 TEST_F(DebugNumericSummaryOpCustomLowerBoundTest, Float_full_house) {
646   TF_ASSERT_OK(Init(DT_FLOAT));
647   AddInputFromArray<float>(
648       TensorShape({18}),
649       {std::numeric_limits<float>::quiet_NaN(),
650        std::numeric_limits<float>::quiet_NaN(), 0.0f, 0.0f, 0.0f, -1.0f, -3.0f,
651        3.0f, 7.0f, -std::numeric_limits<float>::infinity(),
652        -std::numeric_limits<float>::infinity(),
653        std::numeric_limits<float>::infinity(),
654        std::numeric_limits<float>::infinity(),
655        std::numeric_limits<float>::infinity(),
656        std::numeric_limits<float>::infinity(),
657        std::numeric_limits<float>::infinity(),
658        std::numeric_limits<float>::quiet_NaN(),
659        std::numeric_limits<float>::quiet_NaN()});
660   TF_ASSERT_OK(RunOpKernel());
661 
662   Tensor expected(allocator(), DT_DOUBLE, TensorShape({15}));
663   test::FillValues<double>(
664       &expected,
665       {1.0,            // Is initialized.
666        18.0,           // Total element count.
667        4.0,            // nan count.
668        3.0,            // -inf count.
669        1.0,            // negative number count (excluding -inf).
670        3.0,            // zero count.
671        2.0,            // positive number count (excluding +inf).
672        5.0,            // +inf count.
673        -3.0,           // minimum of non-inf and non-nan elements.
674        7.0,            // maximum of non-inf and non-nan elements.
675        0.85714285714,  // mean of non-inf and non-nan elements.
676        8.97959183673,  // variance of non-inf and non-nan elements.
677        static_cast<double>(DT_FLOAT),  // dtype.
678        1.0,                            // Number of dimensions.
679        18.0});                         // Dimension sizes.
680 
681   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
682 }
683 
684 // Tests for DebugNumericSummaryOp
685 class DebugNumericSummaryOpCustomLowerUpperBoundsTest : public OpsTestBase {
686  protected:
Init(DataType input_type)687   Status Init(DataType input_type) {
688     TF_CHECK_OK(NodeDefBuilder("op", "DebugNumericSummary")
689                     .Input(FakeInput(input_type))
690                     .Attr("tensor_name", "FakeTensor:0")
691                     .Attr("lower_bound", -0.5f)
692                     .Attr("upper_bound", 3.6f)
693                     .Finalize(node_def()));
694     return InitOp();
695   }
696 };
697 
TEST_F(DebugNumericSummaryOpCustomLowerUpperBoundsTest,Int32Success)698 TEST_F(DebugNumericSummaryOpCustomLowerUpperBoundsTest, Int32Success) {
699   TF_ASSERT_OK(Init(DT_INT32));
700   AddInputFromArray<int32>(TensorShape({2, 3}), {0, 0, -1, 3, 3, 7});
701   TF_ASSERT_OK(RunOpKernel());
702 
703   Tensor expected(allocator(), DT_DOUBLE, TensorShape({16}));
704   test::FillValues<double>(
705       &expected,
706       {1.0,            // Is initialized.
707        6.0,            // Total element count.
708        0.0,            // nan count.
709        1.0,            // -inf count.
710        0.0,            // negative count (excluding -inf).
711        2.0,            // zero count.
712        2.0,            // positive count (excluding +inf).
713        1.0,            // +inf count.
714        -1.0,           // minimum of non-inf and non-nan elements.
715        7.0,            // maximum of non-inf and non-nan elements.
716        2.0,            // mean of non-inf and non-nan elements.
717        7.33333333333,  // variance of non-inf and non-nan elements.
718        static_cast<double>(DT_INT32),  // dtype.
719        2.0,                            // Number of dimensions.
720        2.0, 3.0});                     // Dimension sizes.
721 
722   test::ExpectTensorNear<double>(expected, *GetOutput(0), 1e-8);
723 }
724 
725 }  // namespace tensorflow
726