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