]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
pytest: add ftp upload tests
authorStefan Eissing <stefan@eissing.org>
Tue, 21 May 2024 10:17:33 +0000 (12:17 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 22 May 2024 07:12:43 +0000 (09:12 +0200)
- refs #13556
- allow anon uploads on vsftpd test server
- add test_30_05 for plain upload of 1k, 100k, 1m
- add test_31_05 for SSL upload of 1k, 100k, 1m
- verify file size and contents

Closes #13734

tests/http/test_30_vsftpd.py
tests/http/test_31_vsftpds.py
tests/http/testenv/curl.py
tests/http/testenv/vsftpd.py

index af52e10f8dac80037c5ddd453552b5bf52fc6e34..11b8902792b2392cd79a8c0244e63dcd9fe92d0f 100644 (file)
@@ -67,6 +67,9 @@ class TestVsFTPD:
         self._make_docs_file(docs_dir=vsftpd.docs_dir, fname='data-10k', fsize=10*1024)
         self._make_docs_file(docs_dir=vsftpd.docs_dir, fname='data-1m', fsize=1024*1024)
         self._make_docs_file(docs_dir=vsftpd.docs_dir, fname='data-10m', fsize=10*1024*1024)
+        env.make_data_file(indir=env.gen_dir, fname="upload-1k", fsize=1024)
+        env.make_data_file(indir=env.gen_dir, fname="upload-100k", fsize=100*1024)
+        env.make_data_file(indir=env.gen_dir, fname="upload-1m", fsize=1024*1024)
 
     def test_30_01_list_dir(self, env: Env, vsftpd: VsFTPD, repeat):
         curl = CurlClient(env=env)
@@ -115,6 +118,24 @@ class TestVsFTPD:
         r.check_stats(count=count, http_status=226)
         self.check_downloads(curl, srcfile, count)
 
+    @pytest.mark.parametrize("docname", [
+        'upload-1k', 'upload-100k', 'upload-1m'
+    ])
+    def test_30_05_upload_1(self, env: Env, vsftpd: VsFTPD, docname, repeat):
+        curl = CurlClient(env=env)
+        srcfile = os.path.join(env.gen_dir, docname)
+        dstfile = os.path.join(vsftpd.docs_dir, docname)
+        self._rmf(dstfile)
+        count = 1
+        url = f'ftp://{env.ftp_domain}:{vsftpd.port}/'
+        r = curl.ftp_upload(urls=[url], fupload=f'{srcfile}', with_stats=True)
+        r.check_stats(count=count, http_status=226)
+        self.check_upload(env, vsftpd, docname=docname)
+
+    def _rmf(self, path):
+        if os.path.exists(path):
+            return os.remove(path)
+
     def check_downloads(self, client, srcfile: str, count: int,
                         complete: bool = True):
         for i in range(count):
@@ -128,5 +149,15 @@ class TestVsFTPD:
                                                     n=1))
                 assert False, f'download {dfile} differs:\n{diff}'
 
-
-
+    def check_upload(self, env, vsftpd: VsFTPD, docname):
+        srcfile = os.path.join(env.gen_dir, docname)
+        dstfile = os.path.join(vsftpd.docs_dir, docname)
+        assert os.path.exists(srcfile)
+        assert os.path.exists(dstfile)
+        if not filecmp.cmp(srcfile, dstfile, shallow=False):
+            diff = "".join(difflib.unified_diff(a=open(srcfile).readlines(),
+                                                b=open(dstfile).readlines(),
+                                                fromfile=srcfile,
+                                                tofile=dstfile,
+                                                n=1))
+            assert False, f'upload {dstfile} differs:\n{diff}'
index 7dd4b3f810f6bac7c8d6d5999d4b98271b4f5cc0..e8d8153f0173261af3c4c2216ddb65623950f041 100644 (file)
@@ -77,6 +77,9 @@ class TestVsFTPD:
         self._make_docs_file(docs_dir=vsftpds.docs_dir, fname='data-10k', fsize=10*1024)
         self._make_docs_file(docs_dir=vsftpds.docs_dir, fname='data-1m', fsize=1024*1024)
         self._make_docs_file(docs_dir=vsftpds.docs_dir, fname='data-10m', fsize=10*1024*1024)
+        env.make_data_file(indir=env.gen_dir, fname="upload-1k", fsize=1024)
+        env.make_data_file(indir=env.gen_dir, fname="upload-100k", fsize=100*1024)
+        env.make_data_file(indir=env.gen_dir, fname="upload-1m", fsize=1024*1024)
 
     def test_31_01_list_dir(self, env: Env, vsftpds: VsFTPD, repeat):
         curl = CurlClient(env=env)
@@ -125,6 +128,24 @@ class TestVsFTPD:
         r.check_stats(count=count, http_status=226)
         self.check_downloads(curl, srcfile, count)
 
+    @pytest.mark.parametrize("docname", [
+        'upload-1k', 'upload-100k', 'upload-1m'
+    ])
+    def test_31_05_upload_1(self, env: Env, vsftpds: VsFTPD, docname, repeat):
+        curl = CurlClient(env=env)
+        srcfile = os.path.join(env.gen_dir, docname)
+        dstfile = os.path.join(vsftpds.docs_dir, docname)
+        self._rmf(dstfile)
+        count = 1
+        url = f'ftp://{env.ftp_domain}:{vsftpds.port}/'
+        r = curl.ftp_ssl_upload(urls=[url], fupload=f'{srcfile}', with_stats=True)
+        r.check_stats(count=count, http_status=226)
+        self.check_upload(env, vsftpds, docname=docname)
+
+    def _rmf(self, path):
+        if os.path.exists(path):
+            return os.remove(path)
+
     def check_downloads(self, client, srcfile: str, count: int,
                         complete: bool = True):
         for i in range(count):
@@ -138,5 +159,16 @@ class TestVsFTPD:
                                                     n=1))
                 assert False, f'download {dfile} differs:\n{diff}'
 
-
+    def check_upload(self, env, vsftpd: VsFTPD, docname):
+        srcfile = os.path.join(env.gen_dir, docname)
+        dstfile = os.path.join(vsftpd.docs_dir, docname)
+        assert os.path.exists(srcfile)
+        assert os.path.exists(dstfile)
+        if not filecmp.cmp(srcfile, dstfile, shallow=False):
+            diff = "".join(difflib.unified_diff(a=open(srcfile).readlines(),
+                                                b=open(dstfile).readlines(),
+                                                fromfile=srcfile,
+                                                tofile=dstfile,
+                                                n=1))
+            assert False, f'upload {dstfile} differs:\n{diff}'
 
index 23b70b293f802df2a1b5e2b4832f7736a8c635f0..f4078646433d134a884363026a3e8643ee7f5325 100644 (file)
@@ -579,6 +579,37 @@ class CurlClient:
                             with_profile=with_profile, no_save=no_save,
                             extra_args=extra_args)
 
+    def ftp_upload(self, urls: List[str], fupload,
+                   with_stats: bool = True,
+                   with_profile: bool = False,
+                   extra_args: List[str] = None):
+        if extra_args is None:
+            extra_args = []
+        extra_args.extend([
+            '--upload-file', fupload
+        ])
+        if with_stats:
+            extra_args.extend([
+                '-w', '%{json}\\n'
+            ])
+        return self._raw(urls, options=extra_args,
+                         with_stats=with_stats,
+                         with_headers=False,
+                         with_profile=with_profile)
+
+    def ftp_ssl_upload(self, urls: List[str], fupload,
+                       with_stats: bool = True,
+                       with_profile: bool = False,
+                       extra_args: List[str] = None):
+        if extra_args is None:
+            extra_args = []
+        extra_args.extend([
+            '--ssl-reqd',
+        ])
+        return self.ftp_upload(urls=urls, fupload=fupload,
+                               with_stats=with_stats, with_profile=with_profile,
+                               extra_args=extra_args)
+
     def response_file(self, idx: int):
         return os.path.join(self._run_dir, f'download_{idx}.data')
 
index 4ba0132e69cff3d7ff3e9ab981e97ec6f502cc82..8daa7b0f662a5cd4aaa919d50ae3712e5e67b68e 100644 (file)
@@ -190,16 +190,19 @@ class VsFTPD:
             f'anonymous_enable=YES',
             f'anon_root={self._docs_dir}',
             f'dirmessage_enable=YES',
+            f'write_enable=YES',
+            f'anon_upload_enable=YES',
             f'log_ftp_protocol=YES',
             f'xferlog_enable=YES',
-            f'xferlog_std_format=YES',
-            f'xferlog_file={self._error_log}',
+            f'xferlog_std_format=NO',
+            f'vsftpd_log_file={self._error_log}',
             f'\n',
         ]
         if self._with_ssl:
             creds = self.env.get_credentials(self.domain)
             conf.extend([
                 f'ssl_enable=YES',
+                f'debug_ssl=YES',
                 f'allow_anon_ssl=YES',
                 f'rsa_cert_file={creds.cert_file}',
                 f'rsa_private_key_file={creds.pkey_file}',