code: def test_loop_state_on_complete_run(tmpdir):
      n_epochs = 3
      n_batches = 3
      accumulate_grad_batches = 1
  
      class TestModel(BoringModel):
          def train_dataloader(self):
              # override to test the `is_last_batch` value
              return DataLoader(RandomDataset(32, n_batches))
  
      model = TestModel()
  
      trainer = Trainer(
          default_root_dir=tmpdir,
          max_epochs=n_epochs,
          limit_val_batches=0,
          accumulate_grad_batches=accumulate_grad_batches,
          enable_progress_bar=False,
          logger=False,
      )
      trainer.fit(model)
  
      assert trainer.num_training_batches == n_batches
  
      ckpt_path = trainer.checkpoint_callback.best_model_path
      assert os.path.exists(ckpt_path)
      checkpoint = torch.load(ckpt_path)
  
      n_sch_steps_total = n_epochs
      n_sch_steps_current = 1
  
      expected = {
          "state_dict": ANY,
          "epoch_progress": {
              "total": {
                  "ready": n_epochs,
                  "started": n_epochs,
                  "processed": n_epochs,
                  "completed": n_epochs - 1,
              },
              "current": {
                  "ready": n_epochs,
                  "started": n_epochs,
                  "processed": n_epochs,
                  "completed": n_epochs - 1,
              },
          },
          "epoch_loop.state_dict": ANY,
          "epoch_loop.batch_progress": {
              "total": {
                  "ready": n_epochs * n_batches,
                  "started": n_epochs * n_batches,
                  "processed": n_epochs * n_batches,
                  "completed": n_epochs * n_batches,
              },
              "current": {
                  "ready": n_batches,
                  "started": n_batches,
                  "processed": n_batches,
                  "completed": n_batches,
              },
              "is_last_batch": True,
          },
          "epoch_loop.scheduler_progress": {
              "total": {
                  "ready": n_sch_steps_total,
                  "completed": n_sch_steps_total,
              },
              "current": {
                  "ready": n_sch_steps_current,
                  "completed": n_sch_steps_current,
              },
          },
          "epoch_loop.manual_optimization.state_dict": ANY,
          "epoch_loop.manual_optimization.optim_step_progress": {
              "total": {"ready": 0, "completed": 0},
              "current": {"ready": 0, "completed": 0},
          },
          "epoch_loop.automatic_optimization.state_dict": {},
          "epoch_loop.automatic_optimization.optim_progress": {
              "optimizer": {
                  "step": {
                      "total": {
                          "ready": n_epochs * n_batches,
                          "completed": n_epochs * n_batches,
                      },
                      "current": {
                          "ready": n_batches,
                          "completed": n_batches,
                      },
                  },
                  "zero_grad": {
                      "total": {
                          "ready": n_epochs * n_batches,
                          "started": n_epochs * n_batches,
                          "completed": n_epochs * n_batches,
                      },
                      "current": {
                          "ready": n_batches,
                          "started": n_batches,
                          "completed": n_batches,
                      },
                  },
              },
          },
          "epoch_loop.val_loop.state_dict": ANY,
          "epoch_loop.val_loop.batch_progress": ANY,
      }
      assert checkpoint["loops"]["fit_loop"] == expected
  
imports: import os
  from copy import deepcopy
  from dataclasses import dataclass
  from typing import Dict, Iterator
  from unittest.mock import ANY, Mock
  import pytest
  import torch
  from lightning.pytorch import LightningModule, Trainer
  from lightning.pytorch.callbacks import Callback, ModelCheckpoint, OnExceptionCheckpoint
  from lightning.pytorch.demos.boring_classes import BoringModel, RandomDataset
  from lightning.pytorch.loops import _Loop
  from lightning.pytorch.loops.progress import _BaseProgress
  from torch.utils.data.dataloader import DataLoader, _MultiProcessingDataLoaderIter
  from tests_pytorch.helpers.runif import RunIf
label_desc: Use image node_id 6 for calling a global function with example usage: test_loop_state_on_complete_run(tmpdir) and returns: DataLoader