logging.exs (22623B)
1 defmodule Ecto.Integration.LoggingTest do 2 use Ecto.Integration.Case, async: true 3 4 alias Ecto.Integration.TestRepo 5 alias Ecto.Integration.PoolRepo 6 alias Ecto.Integration.{Post, Logging, ArrayLogging} 7 8 import ExUnit.CaptureLog 9 import Ecto.Query, only: [from: 2] 10 11 describe "telemetry" do 12 test "dispatches event" do 13 log = fn event_name, measurements, metadata -> 14 assert Enum.at(event_name, -1) == :query 15 assert %{result: {:ok, _res}} = metadata 16 17 assert measurements.total_time == 18 measurements.query_time + measurements.decode_time + measurements.queue_time 19 20 assert measurements.idle_time 21 send(self(), :logged) 22 end 23 24 Process.put(:telemetry, log) 25 _ = PoolRepo.all(Post) 26 assert_received :logged 27 end 28 29 test "dispatches event with stacktrace" do 30 log = fn _event_name, _measurements, metadata -> 31 assert %{stacktrace: [_ | _]} = metadata 32 send(self(), :logged) 33 end 34 35 Process.put(:telemetry, log) 36 _ = PoolRepo.all(Post, stacktrace: true) 37 assert_received :logged 38 end 39 40 test "dispatches event with custom options" do 41 log = fn event_name, _measurements, metadata -> 42 assert Enum.at(event_name, -1) == :query 43 assert metadata.options == [:custom_metadata] 44 send(self(), :logged) 45 end 46 47 Process.put(:telemetry, log) 48 _ = PoolRepo.all(Post, telemetry_options: [:custom_metadata]) 49 assert_received :logged 50 end 51 52 test "dispatches under another event name" do 53 log = fn [:custom], measurements, metadata -> 54 assert %{result: {:ok, _res}} = metadata 55 56 assert measurements.total_time == 57 measurements.query_time + measurements.decode_time + measurements.queue_time 58 59 assert measurements.idle_time 60 send(self(), :logged) 61 end 62 63 Process.put(:telemetry, log) 64 _ = PoolRepo.all(Post, telemetry_event: [:custom]) 65 assert_received :logged 66 end 67 68 test "is not dispatched with no event name" do 69 Process.put(:telemetry, fn _, _ -> raise "never called" end) 70 _ = TestRepo.all(Post, telemetry_event: nil) 71 refute_received :logged 72 end 73 end 74 75 describe "logs" do 76 @stacktrace_opts [stacktrace: true, log: :error] 77 78 defp stacktrace_entry(line) do 79 ~r/↳ anonymous fn\/0 in Ecto.Integration.LoggingTest.\"test logs includes stacktraces\"\/1, at: .*integration_test\/sql\/logging.exs:#{line - 3}/ 80 end 81 82 test "when some measurements are nil" do 83 assert capture_log(fn -> TestRepo.query("BEG", [], log: :error) end) =~ 84 "[error]" 85 end 86 87 test "includes stacktraces" do 88 assert capture_log(fn -> 89 TestRepo.all(Post, @stacktrace_opts) 90 91 :ok 92 end) =~ stacktrace_entry(__ENV__.line) 93 94 assert capture_log(fn -> 95 TestRepo.insert(%Post{}, @stacktrace_opts) 96 97 :ok 98 end) =~ stacktrace_entry(__ENV__.line) 99 100 assert capture_log(fn -> 101 # Test cascading options 102 Ecto.Multi.new() 103 |> Ecto.Multi.insert(:post, %Post{}) 104 |> TestRepo.transaction(@stacktrace_opts) 105 106 :ok 107 end) =~ stacktrace_entry(__ENV__.line) 108 109 assert capture_log(fn -> 110 # In theory we should point to the call _inside_ run 111 # but all multi calls point to the transaction starting point. 112 Ecto.Multi.new() 113 |> Ecto.Multi.run(:all, fn _, _ -> {:ok, TestRepo.all(Post, @stacktrace_opts)} end) 114 |> TestRepo.transaction() 115 116 :ok 117 end) =~ stacktrace_entry(__ENV__.line) 118 end 119 120 test "with custom log level" do 121 assert capture_log(fn -> TestRepo.insert!(%Post{title: "1"}, log: :error) end) =~ 122 "[error]" 123 124 # We cannot assert on the result because it depends on the suite log level 125 capture_log(fn -> 126 TestRepo.insert!(%Post{title: "1"}, log: true) 127 end) 128 129 # But this assertion is always true 130 assert capture_log(fn -> 131 TestRepo.insert!(%Post{title: "1"}, log: false) 132 end) == "" 133 end 134 end 135 136 describe "parameter logging" do 137 @describetag :parameter_logging 138 139 @uuid_regex ~r/[0-9a-f]{2}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i 140 @naive_datetime_regex ~r/~N\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\]/ 141 142 test "for insert_all with query" do 143 # Source query 144 int = 1 145 uuid = Ecto.UUID.generate() 146 147 source_query = 148 from l in Logging, 149 where: l.int == ^int and l.uuid == ^uuid, 150 select: %{uuid: l.uuid, int: l.int} 151 152 # Ensure parameters are complete and in correct order 153 log = 154 capture_log(fn -> 155 TestRepo.insert_all(Logging, source_query, log: :info) 156 end) 157 158 param_regex = ~r/\[(?<int>.+), \"(?<uuid>.+)\"\]/ 159 param_logs = Regex.named_captures(param_regex, log) 160 161 # Query parameters 162 assert param_logs["int"] == Integer.to_string(int) 163 assert param_logs["uuid"] == uuid 164 end 165 166 @tag :insert_select 167 test "for insert_all with entries" do 168 # Row 1 169 int = 1 170 uuid = Ecto.UUID.generate() 171 uuid_query = from l in Logging, where: l.int == ^int and l.uuid == ^uuid, select: l.uuid 172 now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 173 174 row1 = [ 175 int: int, 176 uuid: uuid_query, 177 inserted_at: now, 178 updated_at: now 179 ] 180 181 # Row 2 182 int2 = 2 183 uuid2 = Ecto.UUID.generate() 184 int_query = from l in Logging, where: l.int == ^int2 and l.uuid == ^uuid2, select: l.int 185 now2 = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 186 187 row2 = [ 188 int: int_query, 189 uuid: uuid2, 190 inserted_at: now2, 191 updated_at: now2 192 ] 193 194 # Ensure parameters are complete and in correct order 195 log = 196 capture_log(fn -> 197 TestRepo.insert_all(Logging, [row1, row2], log: :info) 198 end) 199 200 param_regex = 201 ~r/\[\"(?<bid1>.+)\", (?<inserted_at1>.+), (?<int1>.+), (?<updated_at1>.+), (?<uuid1_query_int>.+), \"(?<uuid1_query_uuid>.+)\", \"(?<bid2>.+)\", (?<inserted_at2>.+), (?<int2_query_int>.+), \"(?<int2_query_uuid>.+)\", (?<updated_at2>.+), \"(?<uuid2>.+)\"\]/ 202 203 param_logs = Regex.named_captures(param_regex, log) 204 205 206 # Autogenerated fields 207 assert param_logs["bid1"] =~ @uuid_regex 208 assert param_logs["bid2"] =~ @uuid_regex 209 # Row value parameters 210 assert param_logs["int1"] == Integer.to_string(int) 211 assert param_logs["inserted_at1"] == "~N[#{now}]" 212 assert param_logs["inserted_at2"] == "~N[#{now}]" 213 assert param_logs["uuid1_query_int"] == Integer.to_string(int) 214 assert param_logs["uuid1_query_uuid"] == uuid 215 assert param_logs["int2_query_int"] == Integer.to_string(int2) 216 assert param_logs["int2_query_uuid"] == uuid2 217 assert param_logs["inserted_at2"] == "~N[#{now2}]" 218 assert param_logs["updated_at2"] == "~N[#{now2}]" 219 assert param_logs["uuid2"] == uuid2 220 end 221 222 @tag :insert_select 223 @tag :placeholders 224 test "for insert_all with entries and placeholders" do 225 # Placeholders 226 now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 227 now2 = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 228 placeholder_map = %{now: now, now2: now2} 229 230 # Row 1 231 int = 1 232 uuid = Ecto.UUID.generate() 233 uuid_query = from l in Logging, where: l.int == ^int and l.uuid == ^uuid, select: l.uuid 234 235 row1 = [ 236 int: int, 237 uuid: uuid_query, 238 inserted_at: {:placeholder, :now}, 239 updated_at: {:placeholder, :now} 240 ] 241 242 # Row 2 243 int2 = 2 244 uuid2 = Ecto.UUID.generate() 245 int_query = from l in Logging, where: l.int == ^int2 and l.uuid == ^uuid2, select: l.int 246 247 row2 = [ 248 int: int_query, 249 uuid: uuid2, 250 inserted_at: {:placeholder, :now2}, 251 updated_at: {:placeholder, :now2} 252 ] 253 254 # Ensure parameters are complete and in correct order 255 log = 256 capture_log(fn -> 257 TestRepo.insert_all(Logging, [row1, row2], placeholders: placeholder_map, log: :info) 258 end) 259 260 param_regex = 261 ~r/\[(?<now_placeholder>.+), (?<now2_placeholder>.+), \"(?<bid1>.+)\", (?<int1>.+), (?<uuid1_query_int>.+), \"(?<uuid1_query_uuid>.+)\", \"(?<bid2>.+)\", (?<int2_query_int>.+), \"(?<int2_query_uuid>.+)\", \"(?<uuid2>.+)\"\]/ 262 263 param_logs = Regex.named_captures(param_regex, log) 264 265 # Placeholders 266 assert param_logs["now_placeholder"] == "~N[#{now}]" 267 assert param_logs["now2_placeholder"] == "~N[#{now2}]" 268 # Autogenerated fields 269 assert param_logs["bid1"] =~ @uuid_regex 270 assert param_logs["bid2"] =~ @uuid_regex 271 # Row value parameters 272 assert param_logs["int1"] == Integer.to_string(int) 273 assert param_logs["uuid1_query_int"] == Integer.to_string(int) 274 assert param_logs["uuid1_query_uuid"] == uuid 275 assert param_logs["int2_query_int"] == Integer.to_string(int2) 276 assert param_logs["int2_query_uuid"] == uuid2 277 assert param_logs["uuid2"] == uuid2 278 end 279 280 @tag :with_conflict_target 281 test "for insert_all with query with conflict query" do 282 # Source query 283 int = 1 284 uuid = Ecto.UUID.generate() 285 286 source_query = 287 from l in Logging, 288 where: l.int == ^int and l.uuid == ^uuid, 289 select: %{uuid: l.uuid, int: l.int} 290 291 # Conflict query 292 conflict_int = 0 293 conflict_uuid = Ecto.UUID.generate() 294 conflict_update = 2 295 296 conflict_query = 297 from l in Logging, 298 where: l.int == ^conflict_int and l.uuid == ^conflict_uuid, 299 update: [set: [int: ^conflict_update]] 300 301 # Ensure parameters are complete and in correct order 302 log = 303 capture_log(fn -> 304 TestRepo.insert_all(Logging, source_query, 305 on_conflict: conflict_query, 306 conflict_target: :bid, 307 log: :info 308 ) 309 end) 310 311 param_regex = 312 ~r/\[(?<int>.+), \"(?<uuid>.+)\", (?<conflict_update>.+), (?<conflict_int>.+), \"(?<conflict_uuid>.+)\"\]/ 313 314 param_logs = Regex.named_captures(param_regex, log) 315 316 # Query parameters 317 assert param_logs["int"] == Integer.to_string(int) 318 assert param_logs["uuid"] == uuid 319 # Conflict query parameters 320 assert param_logs["conflict_update"] == Integer.to_string(conflict_update) 321 assert param_logs["conflict_int"] == Integer.to_string(conflict_int) 322 assert param_logs["conflict_uuid"] == conflict_uuid 323 end 324 325 @tag :insert_select 326 @tag :with_conflict_target 327 test "for insert_all with entries conflict query" do 328 # Row 1 329 int = 1 330 uuid = Ecto.UUID.generate() 331 uuid_query = from l in Logging, where: l.int == ^int and l.uuid == ^uuid, select: l.uuid 332 now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 333 334 row1 = [ 335 int: int, 336 uuid: uuid_query, 337 inserted_at: now, 338 updated_at: now 339 ] 340 341 # Row 2 342 int2 = 2 343 uuid2 = Ecto.UUID.generate() 344 int_query = from l in Logging, where: l.int == ^int2 and l.uuid == ^uuid2, select: l.int 345 now2 = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 346 347 row2 = [ 348 int: int_query, 349 uuid: uuid2, 350 inserted_at: now2, 351 updated_at: now2 352 ] 353 354 # Conflict query 355 conflict_int = 0 356 conflict_uuid = Ecto.UUID.generate() 357 conflict_update = 2 358 359 conflict_query = 360 from l in Logging, 361 where: l.int == ^conflict_int and l.uuid == ^conflict_uuid, 362 update: [set: [int: ^conflict_update]] 363 364 # Ensure parameters are complete and in correct order 365 log = 366 capture_log(fn -> 367 TestRepo.insert_all(Logging, [row1, row2], 368 on_conflict: conflict_query, 369 conflict_target: :bid, 370 log: :info 371 ) 372 end) 373 374 param_regex = 375 ~r/\[\"(?<bid1>.+)\", (?<inserted_at1>.+), (?<int1>.+), (?<updated_at1>.+), (?<uuid1_query_int>.+), \"(?<uuid1_query_uuid>.+)\", \"(?<bid2>.+)\", (?<inserted_at2>.+), (?<int2_query_int>.+), \"(?<int2_query_uuid>.+)\", (?<updated_at2>.+), \"(?<uuid2>.+)\", (?<conflict_update>.+), (?<conflict_int>.+), \"(?<conflict_uuid>.+)\"\]/ 376 377 param_logs = Regex.named_captures(param_regex, log) 378 379 # Autogenerated fields 380 assert param_logs["bid1"] =~ @uuid_regex 381 assert param_logs["bid2"] =~ @uuid_regex 382 # Row value parameters 383 assert param_logs["int1"] == Integer.to_string(int) 384 assert param_logs["inserted_at1"] == "~N[#{now2}]" 385 assert param_logs["updated_at1"] == "~N[#{now2}]" 386 assert param_logs["uuid1_query_int"] == Integer.to_string(int) 387 assert param_logs["uuid1_query_uuid"] == uuid 388 assert param_logs["int2_query_int"] == Integer.to_string(int2) 389 assert param_logs["int2_query_uuid"] == uuid2 390 assert param_logs["inserted_at2"] == "~N[#{now2}]" 391 assert param_logs["updated_at2"] == "~N[#{now2}]" 392 assert param_logs["uuid2"] == uuid2 393 # Conflict query parameters 394 assert param_logs["conflict_update"] == Integer.to_string(conflict_update) 395 assert param_logs["conflict_int"] == Integer.to_string(conflict_int) 396 assert param_logs["conflict_uuid"] == conflict_uuid 397 end 398 399 @tag :insert_select 400 @tag :placeholders 401 @tag :with_conflict_target 402 test "for insert_all with entries, placeholders and conflict query" do 403 # Row 1 404 int = 1 405 uuid = Ecto.UUID.generate() 406 uuid_query = from l in Logging, where: l.int == ^int and l.uuid == ^uuid, select: l.uuid 407 408 row1 = [ 409 int: int, 410 uuid: uuid_query, 411 inserted_at: {:placeholder, :now}, 412 updated_at: {:placeholder, :now2} 413 ] 414 415 # Row 2 416 int2 = 2 417 uuid2 = Ecto.UUID.generate() 418 int_query = from l in Logging, where: l.int == ^int2 and l.uuid == ^uuid2, select: l.int 419 420 row2 = [ 421 int: int_query, 422 uuid: uuid2, 423 inserted_at: {:placeholder, :now}, 424 updated_at: {:placeholder, :now2} 425 ] 426 427 # Placeholders 428 now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 429 now2 = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) 430 placeholder_map = %{now: now, now2: now2} 431 432 # Conflict query 433 conflict_int = 0 434 conflict_uuid = Ecto.UUID.generate() 435 conflict_update = 2 436 437 conflict_query = 438 from l in Logging, 439 where: l.int == ^conflict_int and l.uuid == ^conflict_uuid, 440 update: [set: [int: ^conflict_update]] 441 442 # Ensure parameters are complete and in correct order 443 log = 444 capture_log(fn -> 445 TestRepo.insert_all(Logging, [row1, row2], 446 placeholders: placeholder_map, 447 on_conflict: conflict_query, 448 conflict_target: :bid, 449 log: :info 450 ) 451 end) 452 453 param_regex = 454 ~r/\[(?<now_placeholder>.+), (?<now2_placeholder>.+), \"(?<bid1>.+)\", (?<int1>.+), (?<uuid1_query_int>.+), \"(?<uuid1_query_uuid>.+)\", \"(?<bid2>.+)\", (?<int2_query_int>.+), \"(?<int2_query_uuid>.+)\", \"(?<uuid2>.+)\", (?<conflict_update>.+), (?<conflict_int>.+), \"(?<conflict_uuid>.+)\"\]/ 455 456 param_logs = Regex.named_captures(param_regex, log) 457 458 # Placeholders 459 assert param_logs["now_placeholder"] == "~N[#{now}]" 460 assert param_logs["now2_placeholder"] == "~N[#{now2}]" 461 # Autogenerated fields 462 assert param_logs["bid1"] =~ @uuid_regex 463 assert param_logs["bid2"] =~ @uuid_regex 464 # Row value parameters 465 assert param_logs["int1"] == Integer.to_string(int) 466 assert param_logs["uuid1_query_int"] == Integer.to_string(int) 467 assert param_logs["uuid1_query_uuid"] == uuid 468 assert param_logs["int2_query_int"] == Integer.to_string(int2) 469 assert param_logs["int2_query_uuid"] == uuid2 470 assert param_logs["uuid2"] == uuid2 471 # Conflict query parameters 472 assert param_logs["conflict_update"] == Integer.to_string(conflict_update) 473 assert param_logs["conflict_int"] == Integer.to_string(conflict_int) 474 assert param_logs["conflict_uuid"] == conflict_uuid 475 end 476 477 test "for insert" do 478 # Insert values 479 int = 1 480 uuid = Ecto.UUID.generate() 481 482 # Ensure parameters are complete and in correct order 483 log = 484 capture_log(fn -> 485 TestRepo.insert!(%Logging{uuid: uuid, int: int}, 486 log: :info 487 ) 488 end) 489 490 param_regex = 491 ~r/\[(?<int>.+), \"(?<uuid>.+)\", (?<inserted_at>.+), (?<updated_at>.+), \"(?<bid>.+)\"\]/ 492 493 param_logs = Regex.named_captures(param_regex, log) 494 495 # User changes 496 assert param_logs["int"] == Integer.to_string(int) 497 assert param_logs["uuid"] == uuid 498 # Autogenerated changes 499 assert param_logs["inserted_at"] =~ @naive_datetime_regex 500 assert param_logs["updated_at"] =~ @naive_datetime_regex 501 # Filters 502 assert param_logs["bid"] =~ @uuid_regex 503 end 504 505 @tag :with_conflict_target 506 test "for insert with conflict query" do 507 # Insert values 508 int = 1 509 uuid = Ecto.UUID.generate() 510 511 # Conflict query 512 conflict_int = 0 513 conflict_uuid = Ecto.UUID.generate() 514 conflict_update = 2 515 516 conflict_query = 517 from l in Logging, 518 where: l.int == ^conflict_int and l.uuid == ^conflict_uuid, 519 update: [set: [int: ^conflict_update]] 520 521 # Ensure parameters are complete and in correct order 522 log = 523 capture_log(fn -> 524 TestRepo.insert!(%Logging{uuid: uuid, int: int}, 525 on_conflict: conflict_query, 526 conflict_target: :bid, 527 log: :info 528 ) 529 end) 530 531 param_regex = 532 ~r/\[(?<int>.+), \"(?<uuid>.+)\", (?<inserted_at>.+), (?<updated_at>.+), \"(?<bid>.+)\", (?<conflict_update>.+), (?<conflict_int>.+), \"(?<conflict_uuid>.+)\"\]/ 533 534 param_logs = Regex.named_captures(param_regex, log) 535 536 # User changes 537 assert param_logs["int"] == Integer.to_string(int) 538 assert param_logs["uuid"] == uuid 539 # Autogenerated changes 540 assert param_logs["inserted_at"] =~ @naive_datetime_regex 541 assert param_logs["updated_at"] =~ @naive_datetime_regex 542 # Filters 543 assert param_logs["bid"] =~ @uuid_regex 544 # Conflict query parameters 545 assert param_logs["conflict_update"] == Integer.to_string(conflict_update) 546 assert param_logs["conflict_int"] == Integer.to_string(conflict_int) 547 assert param_logs["conflict_uuid"] == conflict_uuid 548 end 549 550 test "for update" do 551 # Update values 552 int = 1 553 uuid = Ecto.UUID.generate() 554 current = TestRepo.insert!(%Logging{}) 555 556 # Ensure parameters are complete and in correct order 557 log = 558 capture_log(fn -> 559 TestRepo.update!(Ecto.Changeset.change(current, %{uuid: uuid, int: int}), log: :info) 560 end) 561 562 param_regex = ~r/\[(?<int>.+), \"(?<uuid>.+)\", (?<updated_at>.+), \"(?<bid>.+)\"\]/ 563 param_logs = Regex.named_captures(param_regex, log) 564 565 # User changes 566 assert param_logs["int"] == Integer.to_string(int) 567 assert param_logs["uuid"] == uuid 568 # Autogenerated changes 569 assert param_logs["updated_at"] =~ @naive_datetime_regex 570 # Filters 571 assert param_logs["bid"] == current.bid 572 end 573 574 test "for delete" do 575 current = TestRepo.insert!(%Logging{}) 576 577 # Ensure parameters are complete and in correct order 578 log = 579 capture_log(fn -> 580 TestRepo.delete!(current, log: :info) 581 end) 582 583 param_regex = ~r/\[\"(?<bid>.+)\"\]/ 584 param_logs = Regex.named_captures(param_regex, log) 585 586 # Filters 587 assert param_logs["bid"] == current.bid 588 end 589 590 test "for queries" do 591 int = 1 592 uuid = Ecto.UUID.generate() 593 594 # all 595 log = 596 capture_log(fn -> 597 TestRepo.all( 598 from(l in Logging, 599 select: type(^"1", :integer), 600 where: l.int == ^int and l.uuid == ^uuid 601 ), 602 log: :info 603 ) 604 end) 605 606 param_regex = ~r/\[(?<tagged_int>.+), (?<int>.+), \"(?<uuid>.+)\"\]/ 607 param_logs = Regex.named_captures(param_regex, log) 608 609 assert param_logs["tagged_int"] == Integer.to_string(int) 610 assert param_logs["int"] == Integer.to_string(int) 611 assert param_logs["uuid"] == uuid 612 613 # update_all 614 update = 2 615 616 log = 617 capture_log(fn -> 618 from(l in Logging, 619 where: l.int == ^int and l.uuid == ^uuid, 620 update: [set: [int: ^update]] 621 ) 622 |> TestRepo.update_all([], log: :info) 623 end) 624 625 param_regex = ~r/\[(?<update>.+), (?<int>.+), \"(?<uuid>.+)\"\]/ 626 param_logs = Regex.named_captures(param_regex, log) 627 628 assert param_logs["update"] == Integer.to_string(update) 629 assert param_logs["int"] == Integer.to_string(int) 630 assert param_logs["uuid"] == uuid 631 632 # delete_all 633 log = 634 capture_log(fn -> 635 TestRepo.delete_all(from(l in Logging, where: l.int == ^int and l.uuid == ^uuid), 636 log: :info 637 ) 638 end) 639 640 param_regex = ~r/\[(?<int>.+), \"(?<uuid>.+)\"\]/ 641 param_logs = Regex.named_captures(param_regex, log) 642 643 assert param_logs["int"] == Integer.to_string(int) 644 assert param_logs["uuid"] == uuid 645 end 646 647 @tag :stream 648 test "for queries with stream" do 649 int = 1 650 uuid = Ecto.UUID.generate() 651 652 log = 653 capture_log(fn -> 654 stream = 655 TestRepo.stream(from(l in Logging, where: l.int == ^int and l.uuid == ^uuid), 656 log: :info 657 ) 658 659 TestRepo.transaction(fn -> Enum.to_list(stream) end) 660 end) 661 662 param_regex = ~r/\[(?<int>.+), \"(?<uuid>.+)\"\]/ 663 param_logs = Regex.named_captures(param_regex, log) 664 665 assert param_logs["int"] == Integer.to_string(int) 666 assert param_logs["uuid"] == uuid 667 end 668 669 @tag :array_type 670 test "for queries with array type" do 671 uuid = Ecto.UUID.generate() 672 uuid2 = Ecto.UUID.generate() 673 674 log = 675 capture_log(fn -> 676 TestRepo.all(from(a in ArrayLogging, where: a.uuids == ^[uuid, uuid2]), 677 log: :info 678 ) 679 end) 680 681 param_regex = ~r/\[(?<uuids>\[.+\])\]/ 682 param_logs = Regex.named_captures(param_regex, log) 683 684 assert param_logs["uuids"] == "[\"#{uuid}\", \"#{uuid2}\"]" 685 end 686 end 687 end