code: def test_early_stopping_save_best_model(self):
      from sklearn.datasets import load_breast_cancer
  
      X, y = load_breast_cancer(return_X_y=True)
      n_estimators = 100
      early_stopping_rounds = 5
      early_stop = xgb.callback.EarlyStopping(
          rounds=early_stopping_rounds, save_best=True
      )
      cls = xgb.XGBClassifier(
          n_estimators=n_estimators,
          eval_metric=tm.eval_error_metric_skl,
          callbacks=[early_stop],
      )
      cls.fit(X, y, eval_set=[(X, y)])
      booster = cls.get_booster()
      dump = booster.get_dump(dump_format="json")
      assert len(dump) == booster.best_iteration + 1
  
      early_stop = xgb.callback.EarlyStopping(
          rounds=early_stopping_rounds, save_best=True
      )
      cls = xgb.XGBClassifier(
          booster="gblinear",
          n_estimators=10,
          eval_metric=tm.eval_error_metric_skl,
          callbacks=[early_stop],
      )
      with pytest.raises(ValueError):
          cls.fit(X, y, eval_set=[(X, y)])
  
      # No error
      early_stop = xgb.callback.EarlyStopping(
          rounds=early_stopping_rounds, save_best=False
      )
      xgb.XGBClassifier(
          booster="gblinear",
          n_estimators=10,
          eval_metric=tm.eval_error_metric_skl,
          callbacks=[early_stop],
      ).fit(X, y, eval_set=[(X, y)])
  
imports: import json
  import os
  import tempfile
  from typing import Union
  import pytest
  import xgboost
  from xgboost import testing
label_desc: Use image node_id 9 for calling the TestCallbacks obj's underlying member method code with example usage: obj.test_early_stopping_save_best_model() without return types