code: def test_log_artifacts(artifact_path, ftp_mock, tmp_path):
      # Setup FTP mock.
      dest_path_root = "/some/path"
      repo = FTPArtifactRepository("ftp://test_ftp" + dest_path_root)
  
      repo.get_ftp_client = MagicMock()
      call_mock = MagicMock(return_value=ftp_mock)
      repo.get_ftp_client.return_value = MagicMock(__enter__=call_mock)
  
      dirs_created = {dest_path_root}
      files_created = set()
      cwd_history = ["/"]
  
      def mkd_mock(pathname):
          abs_pathname = posixpath.join(cwd_history[-1], pathname)
          if posixpath.dirname(abs_pathname) not in dirs_created:
              raise ftplib.error_perm
          dirs_created.add(abs_pathname)
  
      ftp_mock.mkd = MagicMock(side_effect=mkd_mock)
  
      def cwd_mock(pathname):
          abs_pathname = posixpath.join(cwd_history[-1], pathname)
          if abs_pathname not in dirs_created:
              raise ftplib.error_perm
          cwd_history.append(abs_pathname)
  
      ftp_mock.cwd = MagicMock(side_effect=cwd_mock)
  
      def storbinary_mock(cmd, _):
          head, basename = cmd.split(" ", 1)
          assert head == "STOR"
          assert "/" not in basename
          files_created.add(posixpath.join(cwd_history[-1], basename))
  
      ftp_mock.storbinary = MagicMock(side_effect=storbinary_mock)
  
      # Test
      data = tmp_path.joinpath("data")
      data.mkdir()
      subd = data.joinpath("subdir")
      subd.mkdir()
      subd.joinpath("a.txt").write_text("A")
      subd.joinpath("b.txt").write_text("B")
      subd.joinpath("c.txt").write_text("C")
      subd.joinpath("empty1").mkdir()
      subsubd = subd.joinpath("subsubdir")
      subsubd.mkdir()
      subsubd.joinpath("aa.txt").write_text("AA")
      subsubd.joinpath("bb.txt").write_text("BB")
      subsubd.joinpath("cc.txt").write_text("CC")
      subsubd.joinpath("empty2").mkdir()
  
      dest_path = (
          dest_path_root
          if artifact_path is None
          else posixpath.join(dest_path_root, artifact_path)
      )
      dirs_expected = {
          dest_path,
          posixpath.join(dest_path, "empty1"),
          posixpath.join(dest_path, "subsubdir"),
          posixpath.join(dest_path, "subsubdir", "empty2"),
      }
  
      files_expected = {
          posixpath.join(dest_path, "a.txt"),
          posixpath.join(dest_path, "b.txt"),
          posixpath.join(dest_path, "c.txt"),
          posixpath.join(dest_path, "subsubdir/aa.txt"),
          posixpath.join(dest_path, "subsubdir/bb.txt"),
          posixpath.join(dest_path, "subsubdir/cc.txt"),
      }
  
      for dirs_expected_i in dirs_expected.copy():
          if dirs_expected_i != dest_path_root:
              dirs_expected |= set(
                  __posixpath_parents(
                      dirs_expected_i, root=dest_path_root
                  )
              )
  
      repo.log_artifacts(subd, artifact_path)
      assert dirs_created == dirs_expected
      assert files_created == files_expected
  
imports: import ftplib
  import posixpath
  from ftplib import FTP
  from unittest.mock import MagicMock
  import pytest
  from mlflow.store.artifact.artifact_repository_registry import get_artifact_repository
  from mlflow.store.artifact.ftp_artifact_repo import FTPArtifactRepository
label_desc: Use image node_id 11 for calling a global function with example usage: test_log_artifacts(artifact_path, ftp_mock, tmp_path) without return types