code: def test_eval_step_logging(mock_log_metrics, tmpdir, num_dataloaders):
      """Test that eval step during fit/validate/test is updated correctly."""
  
      class CustomBoringModel(BoringModel):
          def validation_step(
              self, batch, batch_idx, dataloader_idx=None
          ):
              self.log(
                  f"val_log_{self.trainer.state.fn.value}",
                  batch_idx,
                  on_step=True,
                  on_epoch=False,
              )
  
          def test_step(self, batch, batch_idx, dataloader_idx=None):
              self.log(
                  "test_log", batch_idx, on_step=True, on_epoch=False
              )
  
          def val_dataloader(self):
              return [super().val_dataloader()] * num_dataloaders
  
          def test_dataloader(self):
              return [super().test_dataloader()] * num_dataloaders
  
      limit_batches = 4
      max_epochs = 3
      trainer = Trainer(
          default_root_dir=tmpdir,
          max_epochs=max_epochs,
          limit_train_batches=1,
          limit_val_batches=limit_batches,
          limit_test_batches=limit_batches,
          logger=TensorBoardLogger(tmpdir),
      )
      model = CustomBoringModel()
  
      def get_suffix(dl_idx):
          return (
              f"/dataloader_idx_{dl_idx}"
              if num_dataloaders == 2
              else ""
          )
  
      eval_steps = range(limit_batches)
      trainer.fit(model)
      fit_calls = [
          call(
              metrics={f"val_log_fit{get_suffix(dl_idx)}": float(step)},
              step=step + (limit_batches * epoch),
          )
          for epoch in range(max_epochs)
          for dl_idx in range(num_dataloaders)
          for step in eval_steps
      ]
      assert mock_log_metrics.mock_calls == fit_calls
  
      mock_log_metrics.reset_mock()
      trainer.validate(model)
      validate_calls = [
          call(
              metrics={
                  f"val_log_validate{get_suffix(dl_idx)}": float(val)
              },
              step=val,
          )
          for dl_idx in range(num_dataloaders)
          for val in eval_steps
      ]
      assert mock_log_metrics.mock_calls == validate_calls
  
      mock_log_metrics.reset_mock()
      trainer.test(model)
      test_calls = [
          call(
              metrics={f"test_log{get_suffix(dl_idx)}": float(val)},
              step=val,
          )
          for dl_idx in range(num_dataloaders)
          for val in eval_steps
      ]
      assert mock_log_metrics.mock_calls == test_calls
  
imports: import collections
  import itertools
  import os
  from contextlib import redirect_stdout
  from io import StringIO
  from unittest import mock
  from unittest.mock import ANY, call
  import numpy
  import pytest
  import torch
  from lightning.fabric.utilities.imports import _PYTHON_GREATER_EQUAL_3_8_0
  from lightning.pytorch import Trainer, callbacks
  from lightning.pytorch.callbacks.progress.rich_progress import _RICH_AVAILABLE
  from lightning.pytorch.demos.boring_classes import BoringModel, RandomDataset
  from lightning.pytorch.loggers import TensorBoardLogger
  from lightning.pytorch.loops import _EvaluationLoop
  from lightning.pytorch.trainer.states import RunningStage
  from lightning.pytorch.utilities.exceptions import MisconfigurationException
  from torch import Tensor
  from tests_pytorch.helpers.runif import RunIf
label_desc: Use image node_id 18 for calling a global function with example usage: test_eval_step_logging(mock_log_metrics, tmpdir, num_dataloaders) and returns: unknown, unknown, unknown