code: def test_should_stop_mid_epoch(tmpdir):
      """Test that training correctly stops mid epoch and that validation is still called at the right time."""
  
      class TestModel(BoringModel):
          def __init__(self):
              super().__init__()
              self.validation_called_at = None
  
          def training_step(self, batch, batch_idx):
              if batch_idx == 4:
                  self.trainer.should_stop = True
              return super().training_step(batch, batch_idx)
  
          def validation_step(self, *args):
              self.validation_called_at = (
                  self.trainer.current_epoch,
                  self.trainer.global_step,
              )
              return super().validation_step(*args)
  
      model = TestModel()
      trainer = Trainer(
          default_root_dir=tmpdir,
          max_epochs=1,
          limit_train_batches=10,
          limit_val_batches=1,
      )
      trainer.fit(model)
  
      # even though we stopped mid epoch, the fit loop finished normally and the current epoch was increased
      assert trainer.current_epoch == 1
      assert trainer.global_step == 5
      assert model.validation_called_at == (0, 5)
  
file_path: pytorch-lightning/tests/tests_pytorch/loops/test_training_loop.py
imports: import logging
  from unittest.mock import Mock
  import pytest
  import torch
  from lightning.pytorch import Trainer, seed_everything
  from lightning.pytorch.demos.boring_classes import BoringModel
  from lightning.pytorch.loops import _FitLoop
label_desc: Use image node_id 4 for calling a global function with example usage: test_should_stop_mid_epoch(tmpdir) and returns: super, super