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