code: def test_gcd_train_end_date_regressor():
      """Tests train_end_date for data with regressors"""
      data = generate_df_with_reg_for_tests(
          freq="D",
          periods=30,
          train_start_date=datetime.datetime(2018, 1, 1),
          remove_extra_cols=True,
          mask_test_actuals=True,
      )
      regressor_cols = ["regressor1", "regressor2", "regressor_categ"]
      keep_cols = [TIME_COL, VALUE_COL] + regressor_cols
      df = data["df"][keep_cols].copy()
      # Setting NaN values at the end
      df.loc[df.tail(2).index, "regressor1"] = np.nan
      df.loc[df.tail(4).index, "regressor2"] = np.nan
      df.loc[df.tail(6).index, "regressor_categ"] = np.nan
      df.loc[df.tail(8).index, VALUE_COL] = np.nan
  
      # last date with a value
      result_train_end_date = datetime.datetime(2018, 1, 22)
  
      # default train_end_date, default regressor_cols
      with pytest.warns(UserWarning) as record:
          canonical_data_dict = get_canonical_data(
              df=df, train_end_date=None, regressor_cols=None
          )
          assert (
              f"{VALUE_COL} column of the provided time series contains "
              f"null values at the end, or the input `train_end_date` is beyond the last timestamp available. "
              f"Setting `train_end_date` to the last timestamp with a non-null value "
              f"({result_train_end_date})." in record[0].message.args[0]
          )
          assert canonical_data_dict["df"].shape == df.shape
          assert canonical_data_dict["fit_df"].shape == (22, 2)
          assert canonical_data_dict["regressor_cols"] == []
          assert canonical_data_dict["fit_cols"] == [
              TIME_COL,
              VALUE_COL,
          ]
          assert (
              canonical_data_dict["train_end_date"]
              == result_train_end_date
          )
          assert (
              canonical_data_dict["last_date_for_val"]
              == result_train_end_date
          )
          assert canonical_data_dict["last_date_for_reg"] is None
  
      # train_end_date later than last date in df, all available regressor_cols
      with pytest.warns(UserWarning) as record:
          train_end_date = datetime.datetime(2018, 2, 10)
          canonical_data_dict = get_canonical_data(
              df=df,
              train_end_date=train_end_date,
              regressor_cols=regressor_cols,
          )
          assert (
              f"{VALUE_COL} column of the provided time series contains null values at the end, "
              f"or the input `train_end_date` is beyond the last timestamp available."
              in record[0].message.args[0]
          )
          assert canonical_data_dict["fit_df"].shape == (22, 5)
          assert canonical_data_dict["regressor_cols"] == regressor_cols
          assert (
              canonical_data_dict["fit_cols"]
              == [TIME_COL, VALUE_COL] + regressor_cols
          )
          assert canonical_data_dict[
              "train_end_date"
          ] == datetime.datetime(2018, 1, 22)
          assert canonical_data_dict[
              "last_date_for_val"
          ] == datetime.datetime(2018, 1, 22)
          assert canonical_data_dict[
              "last_date_for_reg"
          ] == datetime.datetime(2018, 1, 28)
  
      # train_end_date in between last date in df and last date before null
      # user passes no regressor_cols
      with pytest.warns(UserWarning) as record:
          train_end_date = datetime.datetime(2018, 1, 25)
          canonical_data_dict = get_canonical_data(
              df=df, train_end_date=train_end_date, regressor_cols=None
          )
          assert (
              f"{VALUE_COL} column of the provided time series contains trailing NAs"
              in record[0].message.args[0]
          )
          assert canonical_data_dict["fit_df"].shape == (25, 2)
          assert canonical_data_dict["regressor_cols"] == []
          assert canonical_data_dict["fit_cols"] == [
              TIME_COL,
              VALUE_COL,
          ]
          assert (
              canonical_data_dict["train_end_date"] == train_end_date
          )  # `train_end_date` is unchanged when provided.
          assert canonical_data_dict[
              "last_date_for_val"
          ] == datetime.datetime(2018, 1, 22)
          assert canonical_data_dict["last_date_for_reg"] is None
  
      # train end date equal to last date before null
      # user requests a subset of the regressor_cols
      train_end_date = datetime.datetime(2018, 1, 22)
      regressor_cols = ["regressor2"]
      canonical_data_dict = get_canonical_data(
          df=df,
          train_end_date=train_end_date,
          regressor_cols=regressor_cols,
      )
      assert canonical_data_dict["fit_df"].shape == (22, 3)
      assert canonical_data_dict["regressor_cols"] == regressor_cols
      assert (
          canonical_data_dict["fit_cols"]
          == [TIME_COL, VALUE_COL] + regressor_cols
      )
      assert canonical_data_dict["train_end_date"] == datetime.datetime(
          2018, 1, 22
      )
      assert canonical_data_dict[
          "last_date_for_val"
      ] == datetime.datetime(2018, 1, 22)
      assert canonical_data_dict[
          "last_date_for_reg"
      ] == datetime.datetime(2018, 1, 26)
  
      # train_end_date smaller than last date before null
      # user requests regressor_cols that does not exist in df
      with pytest.warns(UserWarning) as record:
          train_end_date = datetime.datetime(2018, 1, 20)
          regressor_cols = ["regressor1", "regressor4", "regressor5"]
          canonical_data_dict = get_canonical_data(
              df=df,
              train_end_date=train_end_date,
              regressor_cols=regressor_cols,
          )
          assert canonical_data_dict["fit_df"].shape == (20, 3)
          assert canonical_data_dict["regressor_cols"] == ["regressor1"]
          assert canonical_data_dict["fit_cols"] == [
              TIME_COL,
              VALUE_COL,
              "regressor1",
          ]
          assert canonical_data_dict[
              "train_end_date"
          ] == datetime.datetime(2018, 1, 20)
          assert canonical_data_dict[
              "last_date_for_val"
          ] == datetime.datetime(2018, 1, 22)
          assert canonical_data_dict[
              "last_date_for_reg"
          ] == datetime.datetime(2018, 1, 28)
          assert (
              f"The following columns are not available to use as "
              f"regressors: ['regressor4', 'regressor5']"
          ) in record[0].message.args[0]
  
imports: import datetime
  import numpy
  import pandas
  import pytest
  from greykite.common.constants import ADJUSTMENT_DELTA_COL
  from greykite.common.constants import END_TIME_COL
  from greykite.common.constants import METRIC_COL
  from greykite.common.constants import START_TIME_COL
  from greykite.common.constants import TIME_COL
  from greykite.common.constants import VALUE_COL
  from greykite.common.data_loader import DataLoader
  from greykite.common.enums import TimeEnum
  from greykite.common.python_utils import assert_equal
  from greykite.common.testing_utils import generate_df_with_reg_for_tests
  from greykite.common.time_properties import describe_timeseries
  from greykite.common.time_properties import fill_missing_dates
  from greykite.common.time_properties import find_missing_dates
  from greykite.common.time_properties import get_canonical_data
  from greykite.common.time_properties import infer_freq
  from greykite.common.time_properties import min_gap_in_seconds
label_desc: Use image node_id 11 for calling a global function with example usage: test_gcd_train_end_date_regressor() without return types