def test_exists(self): """Test `FTPHost.path.exists`.""" # Regular use of `exists` host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) self.assertTrue(host.path.exists("index.html")) self.assertFalse(host.path.exists("notthere")) # Test if exceptions are propagated. host = test_base.ftp_host_factory(ftp_host_class=FailingFTPHost) self.assertRaises(ftputil.error.FTPOSError, host.path.exists, "index.html")
def test_exists(self): """Test `FTPHost.path.exists`.""" # Regular use of `exists` host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) assert host.path.exists("index.html") assert not host.path.exists("notthere") # Test if exceptions are propagated. host = test_base.ftp_host_factory(ftp_host_class=FailingFTPHost) with pytest.raises(ftputil.error.FTPOSError): host.path.exists("index.html")
def test_exists(self): """Test `FTPHost.path.exists`.""" # Regular use of `exists` host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) self.assertTrue (host.path.exists("index.html")) self.assertFalse(host.path.exists("notthere")) # Test if exceptions are propagated. host = test_base.ftp_host_factory(ftp_host_class=FailingFTPHost) self.assertRaises( ftputil.error.FTPOSError, host.path.exists, "index.html")
def test_caching(self): """Test whether `FTPFile` cache of `FTPHost` object works.""" host = test_base.ftp_host_factory() self.assertEqual(len(host._children), 0) path1 = "path1" path2 = "path2" # Open one file and inspect cache. file1 = host.open(path1, "w") child1 = host._children[0] self.assertEqual(len(host._children), 1) self.assertFalse(child1._file.closed) # Open another file. file2 = host.open(path2, "w") child2 = host._children[1] self.assertEqual(len(host._children), 2) self.assertFalse(child2._file.closed) # Close first file. file1.close() self.assertEqual(len(host._children), 2) self.assertTrue(child1._file.closed) self.assertFalse(child2._file.closed) # Re-open first child's file. file1 = host.open(path1, "w") child1_1 = file1._host # Check if it's reused. self.assertTrue(child1 is child1_1) self.assertFalse(child1._file.closed) self.assertFalse(child2._file.closed) # Close second file. file2.close() self.assertTrue(child2._file.closed)
def _test_stat(session_factory): host = test_base.ftp_host_factory(session_factory=session_factory) stat = ftputil.stat._Stat(host) # Use Unix format parser explicitly. This doesn't exclude switching # to the MS format parser later if the test allows this switching. stat._parser = ftputil.stat.UnixParser() return stat
def test_cache_size_zero(self): host = test_base.ftp_host_factory() with pytest.raises(ValueError): host.stat_cache.resize(0) # If bug #38 was present, this raised an `IndexError`. items = host.listdir(host.curdir) assert items[:3] == ["chemeng", "download", "image"]
def test_synchronize_times_for_server_in_east(self): """Test for timestamp correction (see ticket #55).""" host = test_base.ftp_host_factory(ftp_host_class=TimeShiftFTPHost, session_factory=TimeShiftMockSession) # Set this explicitly to emphasize the problem. host.set_time_shift(0.0) hour = 60 * 60 # This could be any negative time shift. presumed_time_shift = -6 * hour # Set `mtime` to simulate a server east of us. # In case the `time_shift` value for this host instance is 0.0 # (as is to be expected before the time shift is determined), # the directory parser (more specifically # `ftputil.stat.Parser.parse_unix_time`) will return a time which # is a year too far in the past. The `synchronize_times` # method needs to deal with this and add the year "back". # I don't think it's a bug in `parse_unix_time` because the # method should work once the time shift is set correctly. local_time = time.localtime() local_time_with_wrong_year = (local_time.tm_year-1,) + local_time[1:] presumed_server_time = \ time.mktime(local_time_with_wrong_year) + presumed_time_shift host.path.set_mtime(presumed_server_time) host.synchronize_times() self.assertEqual(host.time_shift(), presumed_time_shift)
def test_regular_isdir_isfile_islink(self): """Test regular `FTPHost._Path.isdir/isfile/islink`.""" host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) # Test a path which isn't there. self.assertFalse(host.path.isdir ("notthere")) self.assertFalse(host.path.isfile("notthere")) self.assertFalse(host.path.islink("notthere")) # This checks additional code (see ticket #66). self.assertFalse(host.path.isdir ("/notthere/notthere")) self.assertFalse(host.path.isfile("/notthere/notthere")) self.assertFalse(host.path.islink("/notthere/notthere")) # Test a directory. self.assertTrue (host.path.isdir (testdir)) self.assertFalse(host.path.isfile(testdir)) self.assertFalse(host.path.islink(testdir)) # Test a file. testfile = "/home/sschwarzer/index.html" self.assertFalse(host.path.isdir (testfile)) self.assertTrue (host.path.isfile(testfile)) self.assertFalse(host.path.islink(testfile)) # Test a link. Since the link target of `osup` doesn't exist, # neither `isdir` nor `isfile` return `True`. testlink = "/home/sschwarzer/osup" self.assertFalse(host.path.isdir (testlink)) self.assertFalse(host.path.isfile(testlink)) self.assertTrue (host.path.islink(testlink))
def test_regular_isdir_isfile_islink(self): """Test regular `FTPHost._Path.isdir/isfile/islink`.""" host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) # Test a path which isn't there. assert not host.path.isdir("notthere") assert not host.path.isfile("notthere") assert not host.path.islink("notthere") # This checks additional code (see ticket #66). assert not host.path.isdir("/notthere/notthere") assert not host.path.isfile("/notthere/notthere") assert not host.path.islink("/notthere/notthere") # Test a directory. assert host.path.isdir(testdir) assert not host.path.isfile(testdir) assert not host.path.islink(testdir) # Test a file. testfile = "/home/sschwarzer/index.html" assert not host.path.isdir(testfile) assert host.path.isfile(testfile) assert not host.path.islink(testfile) # Test a link. Since the link target of `osup` doesn't exist, # neither `isdir` nor `isfile` return `True`. testlink = "/home/sschwarzer/osup" assert not host.path.isdir(testlink) assert not host.path.isfile(testlink) assert host.path.islink(testlink)
def test_caching(self): """Test whether `FTPFile` cache of `FTPHost` object works.""" host = test_base.ftp_host_factory() assert len(host._children) == 0 path1 = "path1" path2 = "path2" # Open one file and inspect cache. file1 = host.open(path1, "w") child1 = host._children[0] assert len(host._children) == 1 assert not child1._file.closed # Open another file. file2 = host.open(path2, "w") child2 = host._children[1] assert len(host._children) == 2 assert not child2._file.closed # Close first file. file1.close() assert len(host._children) == 2 assert child1._file.closed assert not child2._file.closed # Re-open first child's file. file1 = host.open(path1, "w") child1_1 = file1._host # Check if it's reused. assert child1 is child1_1 assert not child1._file.closed assert not child2._file.closed # Close second file. file2.close() assert child2._file.closed
def test_synchronize_times_for_server_in_east(self): """Test for timestamp correction (see ticket #55).""" host = test_base.ftp_host_factory(ftp_host_class=TimeShiftFTPHost, session_factory=TimeShiftMockSession) # Set this explicitly to emphasize the problem. host.set_time_shift(0.0) hour = 60 * 60 # This could be any negative time shift. presumed_time_shift = -6 * hour # Set `mtime` to simulate a server east of us. # In case the `time_shift` value for this host instance is 0.0 # (as is to be expected before the time shift is determined), # the directory parser (more specifically # `ftputil.stat.Parser.parse_unix_time`) will return a time which # is a year too far in the past. The `synchronize_times` # method needs to deal with this and add the year "back". # I don't think it's a bug in `parse_unix_time` because the # method should work once the time shift is set correctly. local_time = time.localtime() local_time_with_wrong_year = (local_time.tm_year - 1, ) + local_time[1:] presumed_server_time = \ time.mktime(local_time_with_wrong_year) + presumed_time_shift host.path.set_mtime(presumed_server_time) host.synchronize_times() self.assertEqual(host.time_shift(), presumed_time_shift)
def test_plain_listing(self): host = test_base.ftp_host_factory( session_factory=RecursiveListingForDotAsPathSession) lines = host._dir("") self.assertEqual(lines[0], "total 10") self.assertTrue(lines[1].startswith("lrwxrwxrwx 1 staff")) self.assertTrue(lines[2].startswith("d--x--x--x 2 staff")) host.close()
def test_download(self): """Test whether `download` accepts either unicode or bytes.""" host = test_base.ftp_host_factory( session_factory=BinaryDownloadMockSession) local_file_name = "_local_target_" host.download("source", local_file_name) host.download(ftputil.tool.as_bytes("source"), local_file_name) os.remove(local_file_name)
def test_recursive_listing(self): host = test_base.ftp_host_factory( session_factory=RecursiveListingForDotAsPathSession) lines = host._dir(host.curdir) assert lines[0] == "total 10" assert lines[1].startswith("lrwxrwxrwx 1 staff") assert lines[2].startswith("d--x--x--x 2 staff") host.close()
def test_isdir_isfile_with_infinite_link_chain(self): """ Test if `isdir` and `isfile` return `False` if they encounter an infinite link chain. """ host = test_base.ftp_host_factory() assert host.path.isdir("/home/bad_link") is False assert host.path.isfile("/home/bad_link") is False
def test_failing_pickling(self): """Test if pickling (intentionally) isn't supported.""" with test_base.ftp_host_factory() as host: with pytest.raises(TypeError): pickle.dumps(host) with host.open("/home/sschwarzer/index.html") as file_obj: with pytest.raises(TypeError): pickle.dumps(file_obj)
def test_ftputil_exception(self): with pytest.raises(ftputil.error.FTPOSError): with test_base.ftp_host_factory(FailOnLoginSession) as host: pass # We arrived here, that's fine. Because the `FTPHost` object # wasn't successfully constructed, the assignment to `host` # shouldn't have happened. assert "host" not in locals()
def test_normal_operation(self): with test_base.ftp_host_factory(session_factory=ReadMockSession) as host: with host.open("dummy", "r") as f: self.assertEqual(f.closed, False) data = f.readline() self.assertEqual(data, "line 1\n") self.assertEqual(f.closed, False) self.assertEqual(f.closed, True)
def test_open_and_close(self): """ Test if opening and closing an `FTPHost` object works as expected. """ host = test_base.ftp_host_factory() host.close() assert host.closed is True assert host._children == []
def test_client_code_exception(self): try: with test_base.ftp_host_factory() as host: assert host.closed is False raise ClientCodeException() except ClientCodeException: assert host.closed is True else: pytest.fail("`ClientCodeException` not raised")
def test_normal_operation(self): with test_base.ftp_host_factory( session_factory=ReadMockSession) as host: with host.open("dummy", "r") as fobj: assert fobj.closed is False data = fobj.readline() assert data == "line 1\n" assert fobj.closed is False assert fobj.closed is True
def test_ascii_readlines(self): """Read ASCII text with `readlines`.""" host = test_base.ftp_host_factory(session_factory=ReadMockSession) input_ = host.open("dummy", "r") data = input_.read(3) self.assertEqual(data, "lin") data = input_.readlines() self.assertEqual(data, ["e 1\n", "another line\n", "yet another line"]) input_.close()
def test_set_parser(self): """Test if the selected parser is used.""" host = test_base.ftp_host_factory() self.assertEqual(host._stat._allow_parser_switching, True) trivial_parser = TestSetParser.TrivialParser() host.set_parser(trivial_parser) stat_result = host.stat("/home") self.assertEqual(stat_result, trivial_parser.default_stat_result) self.assertEqual(host._stat._allow_parser_switching, False)
def test_set_parser(self): """Test if the selected parser is used.""" host = test_base.ftp_host_factory() assert host._stat._allow_parser_switching is True trivial_parser = TestSetParser.TrivialParser() host.set_parser(trivial_parser) stat_result = host.stat("/home") assert stat_result == trivial_parser.default_stat_result assert host._stat._allow_parser_switching is False
def test_client_code_exception(self): try: with test_base.ftp_host_factory() as host: self.assertEqual(host.closed, False) raise ClientCodeException() except ClientCodeException: self.assertEqual(host.closed, True) else: raise self.failureException("ClientCodeException not raised")
def test_normal_operation(self): with test_base.ftp_host_factory( session_factory=ReadMockSession) as host: with host.open("dummy", "r") as f: self.assertEqual(f.closed, False) data = f.readline() self.assertEqual(data, "line 1\n") self.assertEqual(f.closed, False) self.assertEqual(f.closed, True)
def test_binary_write(self): """Write binary data with `write`.""" host = test_base.ftp_host_factory() data = b"\000a\001b\r\n\002c\003\n\004\r\005" with host.open("dummy", "wb") as output: output.write(data) child_data = mock_ftplib.content_of("dummy") expected_data = data self.assertEqual(child_data, expected_data)
def test_ascii_readlines(self): """Read ASCII text with `readlines`.""" host = test_base.ftp_host_factory(session_factory=ReadMockSession) input_ = host.open("dummy", "r") data = input_.read(3) assert data == "lin" data = input_.readlines() assert data == ["e 1\n", "another line\n", "yet another line"] input_.close()
def test_binary_write(self): """Write binary data with `write`.""" host = test_base.ftp_host_factory() data = b"\000a\001b\r\n\002c\003\n\004\r\005" with host.open("dummy", "wb") as output: output.write(data) child_data = mock_ftplib.content_of("dummy") expected_data = data assert child_data == expected_data
def test_isdir_isfile_islink_with_exception(self): """Test failing `FTPHost._Path.isdir/isfile/islink`.""" host = test_base.ftp_host_factory(ftp_host_class=FailingFTPHost) testdir = "/home/sschwarzer" host.chdir(testdir) # Test if exceptions are propagated. FTPOSError = ftputil.error.FTPOSError self.assertRaises(FTPOSError, host.path.isdir, "index.html") self.assertRaises(FTPOSError, host.path.isfile, "index.html") self.assertRaises(FTPOSError, host.path.islink, "index.html")
def test_ascii_write(self): """Write ASCII text with `write`.""" host = test_base.ftp_host_factory() data = " \nline 2\nline 3" with host.open("dummy", "w", newline="\r\n") as output: output.write(data) child_data = mock_ftplib.content_of("dummy") # This corresponds to the byte stream, so expect a `bytes` object. expected_data = b" \r\nline 2\r\nline 3" assert child_data == expected_data
def test_workaround_for_spaces(self): """Test whether the workaround for space-containing paths is used.""" host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) # Test a file name containing spaces. testfile = "/home/dir with spaces/file with spaces" assert not host.path.isdir(testfile) assert host.path.isfile(testfile) assert not host.path.islink(testfile)
def test_workaround_for_spaces(self): """Test whether the workaround for space-containing paths is used.""" host = test_base.ftp_host_factory() testdir = "/home/sschwarzer" host.chdir(testdir) # Test a file name containing spaces. testfile = "/home/dir with spaces/file with spaces" self.assertFalse(host.path.isdir (testfile)) self.assertTrue (host.path.isfile(testfile)) self.assertFalse(host.path.islink(testfile))
def test_client_code_exception(self): with test_base.ftp_host_factory(session_factory=ReadMockSession) as host: try: with host.open("dummy", "r") as f: self.assertEqual(f.closed, False) raise ClientCodeException() except ClientCodeException: self.assertEqual(f.closed, True) else: raise self.failureException("ClientCodeException not raised")
def test_ascii_write(self): """Write ASCII text with `write`.""" host = test_base.ftp_host_factory() data = " \nline 2\nline 3" with host.open("dummy", "w", newline="\r\n") as output: output.write(data) child_data = mock_ftplib.content_of("dummy") # This corresponds to the byte stream, so expect a `bytes` object. expected_data = b" \r\nline 2\r\nline 3" self.assertEqual(child_data, expected_data)
def test_command_not_implemented_error(self): """ Test if we get the anticipated exception if a command isn't implemented by the server. """ host = test_base.ftp_host_factory() self.assertRaises(ftputil.error.CommandNotImplementedError, host.chmod, "nonexistent", 0o644) # `CommandNotImplementedError` is a subclass of `PermanentError`. self.assertRaises(ftputil.error.PermanentError, host.chmod, "nonexistent", 0o644)
def test_conditional_download_with_older_target(self): """Test conditional binary mode download with newer source file.""" local_target = "_test_target_" # Make target file. open(local_target, "w").close() # Source is newer (date in 2020), so download. host = test_base.ftp_host_factory( session_factory=BinaryDownloadMockSession) flag = host.download_if_newer("/home/newer", local_target) self.assertEqual(flag, True) self.compare_and_delete_downloaded_data(local_target)
def test_synchronize_times(self): """Test time synchronization with server.""" host = test_base.ftp_host_factory(ftp_host_class=TimeShiftFTPHost, session_factory=TimeShiftMockSession) # Valid time shift host.path.set_mtime(time.time() + 3630) host.synchronize_times() self.assertEqual(host.time_shift(), 3600) # Invalid time shift host.path.set_mtime(time.time() + 3600 + 10 * 60) self.assertRaises(ftputil.error.TimeShiftError, host.synchronize_times)
def test_synchronize_times(self): """Test time synchronization with server.""" host = test_base.ftp_host_factory(ftp_host_class=TimeShiftFTPHost, session_factory=TimeShiftMockSession) # Valid time shift host.path.set_mtime(time.time() + 3630) host.synchronize_times() self.assertEqual(host.time_shift(), 3600) # Invalid time shift host.path.set_mtime(time.time() + 3600+10*60) self.assertRaises(ftputil.error.TimeShiftError, host.synchronize_times)
def test_ftputil_exception(self): with test_base.ftp_host_factory( session_factory=InaccessibleDirSession) as host: with pytest.raises(ftputil.error.FTPIOError): # This should fail since the directory isn't # accessible by definition. with host.open("/inaccessible/new_file", "w") as fobj: pass # The file construction shouldn't have succeeded, so `fobj` # should be absent from the local namespace. assert "fobj" not in locals()
def test_client_code_exception(self): with test_base.ftp_host_factory( session_factory=ReadMockSession) as host: try: with host.open("dummy", "r") as fobj: assert fobj.closed is False raise ClientCodeException() except ClientCodeException: assert fobj.closed is True else: pytest.fail("`ClientCodeException` not raised")
def test_ftputil_exception(self): try: with test_base.ftp_host_factory(FailOnLoginSession) as host: pass except ftputil.error.FTPOSError: # We arrived here, that's fine. Because the `FTPHost` object # wasn't successfully constructed, the assignment to `host` # shouldn't have happened. self.assertFalse("host" in locals()) else: raise self.failureException("ftputil.error.FTPOSError not raised")
def test_conditional_download_without_target(self): """ Test conditional binary mode download when no target file exists. """ local_target = "_test_target_" # Target does not exist, so download. host = test_base.ftp_host_factory( session_factory=BinaryDownloadMockSession) flag = host.download_if_newer("/home/newer", local_target) self.assertEqual(flag, True) self.compare_and_delete_downloaded_data(local_target)
def test_conditional_download_with_newer_target(self): """Test conditional binary mode download with older source file.""" local_target = "_test_target_" # Make target file. open(local_target, "w").close() # Source is older (date in 1970), so don't download. host = test_base.ftp_host_factory( ftp_host_class=FailingUploadAndDownloadFTPHost, session_factory=BinaryDownloadMockSession) flag = host.download_if_newer("/home/older", local_target) self.assertEqual(flag, False) # Remove target file os.unlink(local_target)
def test_ftputil_exception(self): with test_base.ftp_host_factory(session_factory=InaccessibleDirSession) as host: try: # This should fail since the directory isn't accessible # by definition. with host.open("/inaccessible/new_file", "w") as f: pass except ftputil.error.FTPIOError: # The file construction shouldn't have succeeded, so # `f` should be absent from the local namespace. self.assertFalse("f" in locals()) else: raise self.failureException("ftputil.error.FTPIOError not raised")
def test_ascii_writelines(self): """Write ASCII text with `writelines`.""" host = test_base.ftp_host_factory() data = [" \n", "line 2\n", "line 3"] backup_data = data[:] output = host.open("dummy", "w", newline="\r\n") output.writelines(data) output.close() child_data = mock_ftplib.content_of("dummy") expected_data = b" \r\nline 2\r\nline 3" self.assertEqual(child_data, expected_data) # Ensure that the original data was not modified. self.assertEqual(data, backup_data)
def test_ascii_iterator(self): """ Test the iterator interface of `FTPFile` objects (with newline conversion). """ host = test_base.ftp_host_factory(session_factory=ReadMockSession) input_ = host.open("dummy") input_iterator = iter(input_) self.assertEqual(next(input_iterator), "line 1\n") self.assertEqual(next(input_iterator), "another line\n") self.assertEqual(next(input_iterator), "yet another line") self.assertRaises(StopIteration, input_iterator.__next__) input_.close()
def test_download(self): """Test mode download.""" local_target = "_test_target_" host = test_base.ftp_host_factory( session_factory=BinaryDownloadMockSession) # Download host.download("dummy", local_target) # Read file and compare with open(local_target, "rb") as fobj: data = fobj.read() remote_file_content = mock_ftplib.content_of("dummy") self.assertEqual(data, remote_file_content) # Clean up os.unlink(local_target)
def test_ascii_read(self): """Read ASCII text with plain `read`.""" host = test_base.ftp_host_factory(session_factory=ReadMockSession) with host.open("dummy", "r") as input_: data = input_.read(0) self.assertEqual(data, "") data = input_.read(3) self.assertEqual(data, "lin") data = input_.read(7) self.assertEqual(data, "e 1\nano") data = input_.read() self.assertEqual(data, "ther line\nyet another line") data = input_.read() self.assertEqual(data, "")
def test_conditional_upload(self): """Test conditional upload.""" local_source = "_test_source_" data = binary_data() self.generate_file(data, local_source) # Target is newer, so don't upload. host = test_base.ftp_host_factory( ftp_host_class=FailingUploadAndDownloadFTPHost) flag = host.upload_if_newer(local_source, "/home/newer") self.assertEqual(flag, False) # Target is older, so upload. host = test_base.ftp_host_factory() flag = host.upload_if_newer(local_source, "/home/older") self.assertEqual(flag, True) remote_file_content = mock_ftplib.content_of("older") self.assertEqual(data, remote_file_content) # Target doesn't exist, so upload. host = test_base.ftp_host_factory() flag = host.upload_if_newer(local_source, "/home/notthere") self.assertEqual(flag, True) remote_file_content = mock_ftplib.content_of("notthere") self.assertEqual(data, remote_file_content) # Clean up. os.unlink(local_source)
def test_binary_readline(self): """Read binary data with `readline`.""" host = test_base.ftp_host_factory(session_factory=ReadMockSession) input_ = host.open("dummy", "rb") data = input_.readline(3) self.assertEqual(data, b"lin") data = input_.readline(10) self.assertEqual(data, b"e 1\r\n") data = input_.readline(13) self.assertEqual(data, b"another line\r") data = input_.readline() self.assertEqual(data, b"\n") data = input_.readline() self.assertEqual(data, b"yet another line") data = input_.readline() self.assertEqual(data, b"") input_.close()
def test_assert_valid_time_shift(self): """Test time shift sanity checks.""" host = test_base.ftp_host_factory(session_factory=TimeShiftMockSession) # Use private bound method. assert_time_shift = host._FTPHost__assert_valid_time_shift # Valid time shifts test_data = [23*3600, -23*3600, 3600+30, -3600+30] for time_shift in test_data: self.assertTrue(assert_time_shift(time_shift) is None) # Invalid time shift (exceeds one day) self.assertRaises(ftputil.error.TimeShiftError, assert_time_shift, 25*3600) self.assertRaises(ftputil.error.TimeShiftError, assert_time_shift, -25*3600) # Invalid time shift (too large deviation from full hours unacceptable) self.assertRaises(ftputil.error.TimeShiftError, assert_time_shift, 10*60) self.assertRaises(ftputil.error.TimeShiftError, assert_time_shift, -3600-10*60)
def test_rounded_time_shift(self): """Test if time shift is rounded correctly.""" host = test_base.ftp_host_factory(session_factory=TimeShiftMockSession) # Use private bound method. rounded_time_shift = host._FTPHost__rounded_time_shift # Pairs consisting of original value and expected result test_data = [ ( 0, 0), ( 0.1, 0), ( -0.1, 0), ( 1500, 0), ( -1500, 0), ( 1800, 3600), ( -1800, -3600), ( 2000, 3600), ( -2000, -3600), ( 5*3600-100, 5*3600), (-5*3600+100, -5*3600)] for time_shift, expected_time_shift in test_data: calculated_time_shift = rounded_time_shift(time_shift) self.assertEqual(calculated_time_shift, expected_time_shift)