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"""Tests for tensorflow.kernels.logging_ops.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21import os 22import string 23import sys 24import tempfile 25 26from tensorflow.python.eager import context 27from tensorflow.python.eager import function 28from tensorflow.python.framework import constant_op 29from tensorflow.python.framework import dtypes 30from tensorflow.python.framework import ops 31from tensorflow.python.framework import sparse_tensor 32from tensorflow.python.framework import test_util 33from tensorflow.python.ops import control_flow_ops 34from tensorflow.python.ops import gradients_impl 35from tensorflow.python.ops import logging_ops 36from tensorflow.python.ops import math_ops 37from tensorflow.python.ops import string_ops 38from tensorflow.python.ops import variables 39from tensorflow.python.platform import test 40 41 42class LoggingOpsTest(test.TestCase): 43 44 @test_util.run_deprecated_v1 45 def testAssertDivideByZero(self): 46 with self.cached_session() as sess: 47 epsilon = ops.convert_to_tensor(1e-20) 48 x = ops.convert_to_tensor(0.0) 49 y = ops.convert_to_tensor(1.0) 50 z = ops.convert_to_tensor(2.0) 51 # assert(epsilon < y) 52 # z / y 53 with sess.graph.control_dependencies([ 54 control_flow_ops.Assert( 55 math_ops.less(epsilon, y), ["Divide-by-zero"]) 56 ]): 57 out = math_ops.div(z, y) 58 self.assertAllEqual(2.0, self.evaluate(out)) 59 # assert(epsilon < x) 60 # z / x 61 # 62 # This tests printing out multiple tensors 63 with sess.graph.control_dependencies([ 64 control_flow_ops.Assert( 65 math_ops.less(epsilon, x), ["Divide-by-zero", "less than x"]) 66 ]): 67 out = math_ops.div(z, x) 68 with self.assertRaisesOpError("less than x"): 69 self.evaluate(out) 70 71 72@test_util.run_all_in_graph_and_eager_modes 73class PrintV2Test(test.TestCase): 74 75 def testPrintOneTensor(self): 76 tensor = math_ops.range(10) 77 with self.captureWritesToStream(sys.stderr) as printed: 78 print_op = logging_ops.print_v2(tensor) 79 self.evaluate(print_op) 80 81 expected = "[0 1 2 ... 7 8 9]" 82 self.assertIn((expected + "\n"), printed.contents()) 83 84 def testPrintOneStringTensor(self): 85 tensor = ops.convert_to_tensor([char for char in string.ascii_lowercase]) 86 with self.captureWritesToStream(sys.stderr) as printed: 87 print_op = logging_ops.print_v2(tensor) 88 self.evaluate(print_op) 89 90 expected = "[\"a\" \"b\" \"c\" ... \"x\" \"y\" \"z\"]" 91 self.assertIn((expected + "\n"), printed.contents()) 92 93 def testPrintOneTensorVarySummarize(self): 94 tensor = math_ops.range(10) 95 with self.captureWritesToStream(sys.stderr) as printed: 96 print_op = logging_ops.print_v2(tensor, summarize=1) 97 self.evaluate(print_op) 98 99 expected = "[0 ... 9]" 100 self.assertIn((expected + "\n"), printed.contents()) 101 102 tensor = math_ops.range(10) 103 with self.captureWritesToStream(sys.stderr) as printed: 104 print_op = logging_ops.print_v2(tensor, summarize=2) 105 self.evaluate(print_op) 106 107 expected = "[0 1 ... 8 9]" 108 self.assertIn((expected + "\n"), printed.contents()) 109 110 tensor = math_ops.range(10) 111 with self.captureWritesToStream(sys.stderr) as printed: 112 print_op = logging_ops.print_v2(tensor, summarize=3) 113 self.evaluate(print_op) 114 115 expected = "[0 1 2 ... 7 8 9]" 116 self.assertIn((expected + "\n"), printed.contents()) 117 118 tensor = math_ops.range(10) 119 with self.captureWritesToStream(sys.stderr) as printed: 120 print_op = logging_ops.print_v2(tensor, summarize=-1) 121 self.evaluate(print_op) 122 123 expected = "[0 1 2 3 4 5 6 7 8 9]" 124 self.assertIn((expected + "\n"), printed.contents()) 125 126 def testPrintOneVariable(self): 127 var = variables.Variable(math_ops.range(10)) 128 if not context.executing_eagerly(): 129 self.evaluate(variables.global_variables_initializer()) 130 with self.captureWritesToStream(sys.stderr) as printed: 131 print_op = logging_ops.print_v2(var) 132 self.evaluate(print_op) 133 expected = "[0 1 2 ... 7 8 9]" 134 self.assertIn((expected + "\n"), printed.contents()) 135 136 def testPrintTwoVariablesInStructWithAssignAdd(self): 137 var_one = variables.Variable(2.14) 138 plus_one = var_one.assign_add(1.0) 139 var_two = variables.Variable(math_ops.range(10)) 140 if not context.executing_eagerly(): 141 self.evaluate(variables.global_variables_initializer()) 142 with self.captureWritesToStream(sys.stderr) as printed: 143 self.evaluate(plus_one) 144 print_op = logging_ops.print_v2(var_one, {"second": var_two}) 145 self.evaluate(print_op) 146 expected = "3.14 {'second': [0 1 2 ... 7 8 9]}" 147 self.assertIn((expected + "\n"), printed.contents()) 148 149 def testPrintTwoTensors(self): 150 tensor = math_ops.range(10) 151 with self.captureWritesToStream(sys.stderr) as printed: 152 print_op = logging_ops.print_v2(tensor, tensor * 10) 153 self.evaluate(print_op) 154 expected = "[0 1 2 ... 7 8 9] [0 10 20 ... 70 80 90]" 155 self.assertIn((expected + "\n"), printed.contents()) 156 157 def testPrintTwoTensorsDifferentSep(self): 158 tensor = math_ops.range(10) 159 with self.captureWritesToStream(sys.stderr) as printed: 160 print_op = logging_ops.print_v2(tensor, tensor * 10, sep="<separator>") 161 self.evaluate(print_op) 162 expected = "[0 1 2 ... 7 8 9]<separator>[0 10 20 ... 70 80 90]" 163 self.assertIn(expected + "\n", printed.contents()) 164 165 def testPrintPlaceholderGeneration(self): 166 tensor = math_ops.range(10) 167 with self.captureWritesToStream(sys.stderr) as printed: 168 print_op = logging_ops.print_v2("{}6", {"{}": tensor * 10}) 169 self.evaluate(print_op) 170 expected = "{}6 {'{}': [0 10 20 ... 70 80 90]}" 171 self.assertIn((expected + "\n"), printed.contents()) 172 173 def testPrintNoTensors(self): 174 with self.captureWritesToStream(sys.stderr) as printed: 175 print_op = logging_ops.print_v2(23, [23, 5], {"6": 12}) 176 self.evaluate(print_op) 177 expected = "23 [23, 5] {'6': 12}" 178 self.assertIn((expected + "\n"), printed.contents()) 179 180 def testPrintFloatScalar(self): 181 for dtype in [dtypes.bfloat16, dtypes.half, dtypes.float32, dtypes.float64]: 182 tensor = ops.convert_to_tensor(43.5, dtype=dtype) 183 with self.captureWritesToStream(sys.stderr) as printed: 184 print_op = logging_ops.print_v2(tensor) 185 self.evaluate(print_op) 186 expected = "43.5" 187 self.assertIn((expected + "\n"), printed.contents()) 188 189 def testPrintStringScalar(self): 190 tensor = ops.convert_to_tensor("scalar") 191 with self.captureWritesToStream(sys.stderr) as printed: 192 print_op = logging_ops.print_v2(tensor) 193 self.evaluate(print_op) 194 expected = "scalar" 195 self.assertIn((expected + "\n"), printed.contents()) 196 197 def testPrintStringScalarDifferentEnd(self): 198 tensor = ops.convert_to_tensor("scalar") 199 with self.captureWritesToStream(sys.stderr) as printed: 200 print_op = logging_ops.print_v2(tensor, end="<customend>") 201 self.evaluate(print_op) 202 expected = "scalar<customend>" 203 self.assertIn(expected, printed.contents()) 204 205 def testPrintComplexTensorStruct(self): 206 tensor = math_ops.range(10) 207 small_tensor = constant_op.constant([0.3, 12.4, -16.1]) 208 big_tensor = math_ops.mul(tensor, 10) 209 with self.captureWritesToStream(sys.stderr) as printed: 210 print_op = logging_ops.print_v2( 211 "first:", tensor, "middle:", 212 {"small": small_tensor, "Big": big_tensor}, 10, 213 [tensor * 2, tensor]) 214 self.evaluate(print_op) 215 # Note that the keys in the dict will always be sorted, 216 # so 'Big' comes before 'small' 217 expected = ("first: [0 1 2 ... 7 8 9] " 218 "middle: {'Big': [0 10 20 ... 70 80 90], " 219 "'small': [0.3 12.4 -16.1]} " 220 "10 [[0 2 4 ... 14 16 18], [0 1 2 ... 7 8 9]]") 221 self.assertIn((expected + "\n"), printed.contents()) 222 223 def testPrintSparseTensor(self): 224 ind = [[0, 0], [1, 0], [1, 3], [4, 1], [1, 4], [3, 2], [3, 3]] 225 val = [0, 10, 13, 4, 14, 32, 33] 226 shape = [5, 6] 227 228 sparse = sparse_tensor.SparseTensor( 229 constant_op.constant(ind, dtypes.int64), 230 constant_op.constant(val, dtypes.int64), 231 constant_op.constant(shape, dtypes.int64)) 232 233 with self.captureWritesToStream(sys.stderr) as printed: 234 print_op = logging_ops.print_v2(sparse) 235 self.evaluate(print_op) 236 expected = ("'SparseTensor(indices=[[0 0]\n" 237 " [1 0]\n" 238 " [1 3]\n" 239 " ...\n" 240 " [1 4]\n" 241 " [3 2]\n" 242 " [3 3]], values=[0 10 13 ... 14 32 33], shape=[5 6])'") 243 self.assertIn((expected + "\n"), printed.contents()) 244 245 def testPrintSparseTensorInDataStruct(self): 246 ind = [[0, 0], [1, 0], [1, 3], [4, 1], [1, 4], [3, 2], [3, 3]] 247 val = [0, 10, 13, 4, 14, 32, 33] 248 shape = [5, 6] 249 250 sparse = sparse_tensor.SparseTensor( 251 constant_op.constant(ind, dtypes.int64), 252 constant_op.constant(val, dtypes.int64), 253 constant_op.constant(shape, dtypes.int64)) 254 255 with self.captureWritesToStream(sys.stderr) as printed: 256 print_op = logging_ops.print_v2([sparse]) 257 self.evaluate(print_op) 258 expected = ("['SparseTensor(indices=[[0 0]\n" 259 " [1 0]\n" 260 " [1 3]\n" 261 " ...\n" 262 " [1 4]\n" 263 " [3 2]\n" 264 " [3 3]], values=[0 10 13 ... 14 32 33], shape=[5 6])']") 265 self.assertIn((expected + "\n"), printed.contents()) 266 267 def testPrintOneTensorStdout(self): 268 tensor = math_ops.range(10) 269 with self.captureWritesToStream(sys.stdout) as printed: 270 print_op = logging_ops.print_v2( 271 tensor, output_stream=sys.stdout) 272 self.evaluate(print_op) 273 expected = "[0 1 2 ... 7 8 9]" 274 self.assertIn((expected + "\n"), printed.contents()) 275 276 def testPrintTensorsToFile(self): 277 tmpfile_name = tempfile.mktemp(".printv2_test") 278 tensor_0 = math_ops.range(0, 10) 279 print_op_0 = logging_ops.print_v2(tensor_0, 280 output_stream="file://"+tmpfile_name) 281 self.evaluate(print_op_0) 282 tensor_1 = math_ops.range(11, 20) 283 print_op_1 = logging_ops.print_v2(tensor_1, 284 output_stream="file://"+tmpfile_name) 285 self.evaluate(print_op_1) 286 try: 287 f = open(tmpfile_name, "r") 288 line_0 = f.readline() 289 expected_0 = "[0 1 2 ... 7 8 9]" 290 self.assertTrue(expected_0 in line_0) 291 line_1 = f.readline() 292 expected_1 = "[11 12 13 ... 17 18 19]" 293 self.assertTrue(expected_1 in line_1) 294 f.close() 295 os.remove(tmpfile_name) 296 except IOError as e: 297 self.fail(e) 298 299 def testInvalidOutputStreamRaisesError(self): 300 tensor = math_ops.range(10) 301 with self.assertRaises(ValueError): 302 print_op = logging_ops.print_v2( 303 tensor, output_stream="unknown") 304 self.evaluate(print_op) 305 306 @test_util.run_deprecated_v1 307 def testPrintOpName(self): 308 tensor = math_ops.range(10) 309 print_op = logging_ops.print_v2(tensor, name="print_name") 310 self.assertEqual(print_op.name, "print_name") 311 312 @test_util.run_deprecated_v1 313 def testNoDuplicateFormatOpGraphModeAfterExplicitFormat(self): 314 tensor = math_ops.range(10) 315 formatted_string = string_ops.string_format("{}", tensor) 316 print_op = logging_ops.print_v2(formatted_string) 317 self.evaluate(print_op) 318 graph_ops = ops.get_default_graph().get_operations() 319 format_ops = [op for op in graph_ops if op.type == "StringFormat"] 320 # Should be only 1 format_op for graph mode. 321 self.assertEqual(len(format_ops), 1) 322 323 def testPrintOneTensorEagerOnOpCreate(self): 324 with context.eager_mode(): 325 tensor = math_ops.range(10) 326 expected = "[0 1 2 ... 7 8 9]" 327 with self.captureWritesToStream(sys.stderr) as printed: 328 logging_ops.print_v2(tensor) 329 self.assertIn((expected + "\n"), printed.contents()) 330 331 def testPrintsOrderedInDefun(self): 332 with context.eager_mode(): 333 334 @function.defun 335 def prints(): 336 logging_ops.print_v2("A") 337 logging_ops.print_v2("B") 338 logging_ops.print_v2("C") 339 340 with self.captureWritesToStream(sys.stderr) as printed: 341 prints() 342 self.assertTrue(("A\nB\nC\n"), printed.contents()) 343 344 def testPrintInDefunWithoutExplicitEvalOfPrint(self): 345 @function.defun 346 def f(): 347 tensor = math_ops.range(10) 348 logging_ops.print_v2(tensor) 349 return tensor 350 351 expected = "[0 1 2 ... 7 8 9]" 352 with self.captureWritesToStream(sys.stderr) as printed_one: 353 x = f() 354 self.evaluate(x) 355 self.assertIn((expected + "\n"), printed_one.contents()) 356 357 # We execute the function again to make sure it doesn't only print on the 358 # first call. 359 with self.captureWritesToStream(sys.stderr) as printed_two: 360 y = f() 361 self.evaluate(y) 362 self.assertIn((expected + "\n"), printed_two.contents()) 363 364 365class PrintGradientTest(test.TestCase): 366 367 @test_util.run_in_graph_and_eager_modes 368 def testPrintShape(self): 369 inp = constant_op.constant(2.0, shape=[100, 32]) 370 inp_printed = logging_ops.Print(inp, [inp]) 371 self.assertEqual(inp.get_shape(), inp_printed.get_shape()) 372 373 def testPrintString(self): 374 inp = constant_op.constant(2.0, shape=[100, 32]) 375 inp_printed = logging_ops.Print(inp, ["hello"]) 376 self.assertEqual(inp.get_shape(), inp_printed.get_shape()) 377 378 @test_util.run_deprecated_v1 379 def testPrintGradient(self): 380 inp = constant_op.constant(2.0, shape=[100, 32], name="in") 381 w = constant_op.constant(4.0, shape=[10, 100], name="w") 382 wx = math_ops.matmul(w, inp, name="wx") 383 wx_print = logging_ops.Print(wx, [w, w, w]) 384 wx_grad = gradients_impl.gradients(wx, w)[0] 385 wx_print_grad = gradients_impl.gradients(wx_print, w)[0] 386 wxg = self.evaluate(wx_grad) 387 wxpg = self.evaluate(wx_print_grad) 388 self.assertAllEqual(wxg, wxpg) 389 390 391if __name__ == "__main__": 392 test.main() 393