New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DM-37917: Add testing against real webDAV server for HttpResourcePath #40
Conversation
This makes it consistent with the other interfaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@airnandez thanks for adding these tests. I took the liberty of trying to enable the full ResourcePath test suite now that we have a functioning WebDAV server and not a mocked one. It didn't take many lines to enable it and it did find two compatibility issues.
- When a directory is not created because it's not a directory we have to raise NotADirectoryError (I fixed this).
- When attempting to
uri.write()
when the parent directory does not exist, the other backends make the directory automatically. This does not happen in webdav and so the 4 tests fail with error 409.
Now that we have a WebDAV server involved in the tests I wonder if the mocked test case is worth keeping now. Its main reason to exist is that it tries to test code when there is no webdav server running so maybe that's enough of a reason to keep it but it's now a lot of code to continue to support and it's also not that easy to follow.
* Run generic Resource tests in addition to HTTP-specific tests * Skip tests again plain HTTP servers because they cannot succeed since methods such as mkdir(), exists() for a directory or remove() for a directory are not supported by those servers. * Allow to run the same set of tests against real servers in the development environment by allowing to specify the server URL via an environment variable. * Skip mock-based tests for now that we can run against a real local server launched at test time.
This is fixed now.
I agree that mocking responses is tedious and not very reliable. For the time being, I skip that test as well as all the generic tests that need Also, let me draw your attention to the fact that it is not possible to run the generic tests against a plain HTTP backend, since several methods like Finally, I ran the same set of generic tests and the webDAV-specific tests against 4 different live DAV servers in my development environment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Some minor cleanups suggested (especially removing code completely that we are always skipping).
tests/test_http.py
Outdated
# walk() and we can fully test that GenericTestCase passes against a | ||
# real webDAV server. For the time being we skip it because mocking | ||
# all the possible responses for every possible situation is tedious. | ||
@unittest.skipIf(True, "Skipping test with mocked responses.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather we deleted the test case completely if we have no intention of keeping it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Tests with mocked responses removed.
tests/test_http.py
Outdated
# Execution of GenericTestCase against a plain HTTP server cannot succeed: | ||
# such a server does not support mkdir(), exists() for a directory, remove() | ||
# for a directory. | ||
@unittest.skipIf(True, "Skipping testing with plain HTTP server.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we skipping this? The GenericTestCase code works fine and is there to ensure that the path operations function properly for the HttpResourcePath -- it's specifically designed not to do any I/O and all tests pass when enabled. Please remove the skip and comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong understanding on my side. I reactivated this test.
tests/test_http.py
Outdated
# developer environment by initializing the environment variable | ||
# with the URL of the server, e.g. | ||
# https://dav.example.org:1234/path/to/top/dir | ||
u = urllib.parse.urlparse(test_endpoint) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is in the ResourcePath codebase can we use it rather than the explicit parsing?
test_uri = ResourcePath(test_endpoint, forceDirectory=True)
cls.scheme = test_uri.scheme
cls.netloc = test_uri.netloc
cls.base_path = test_uri.path
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention was to get a clean path, to avoid potential issues with super-sensitive webDAV servers:
>>> p = ResourcePath("https://host.example.org:12345////not/very////clean/path///")
>>> p.path
'////not/very////clean/path///'
By a "clean path" I mean a path in which each component is separated by a single /
, e.g.:
/not/very/clean/path
A path with several separators is syntactically correct, though.
I reverted to use ResourcePath
for parsing.
tests/test_http.py
Outdated
u = urllib.parse.urlparse(test_endpoint) | ||
cls.scheme = u.scheme | ||
cls.netloc = u.netloc | ||
cls.base_path = "/" + u.path.strip("/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we stripping the leading "/" and then adding it back again? Why are we stripping the trailing slash when the code that uses it takes that into account?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above.
python/lsst/resources/tests.py
Outdated
|
||
path = path.lstrip("/") | ||
if self.base_path is not None: | ||
path = self.base_path.strip("/") + "/" + path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably clearer to do:
path = os.path.join(self.base_path, path)
since that will take care of the trailing slash automatically.
|
||
path = path.lstrip("/") | ||
if self.base_path is not None: | ||
path = self.base_path.strip("/") + "/" + path | ||
if path.startswith("/"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path.lstrip
at the top makes this line a no-op I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above.
python/lsst/resources/tests.py
Outdated
@@ -428,7 +436,10 @@ def setUp(self) -> None: | |||
self.tmpdir = ResourcePath(makeTestTempDir(self.testdir)) | |||
else: | |||
# Create tmp directory relative to the test root. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe change to "Create random tmp directory"
shutil.rmtree(cls.webdav_tmpdir, ignore_errors=True) | ||
|
||
def setUp(self): | ||
super().setUp() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a method that just calls super()
can be deleted entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Codecov ReportBase: 84.74% // Head: 84.14% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #40 +/- ##
==========================================
- Coverage 84.74% 84.14% -0.60%
==========================================
Files 27 27
Lines 3415 3476 +61
Branches 713 714 +1
==========================================
+ Hits 2894 2925 +31
- Misses 408 435 +27
- Partials 113 116 +3
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
We are using an external webDAV server to test against. In addition we have the possibility now to test against other real webDAV servers in the develpment setting by specifying via the environment variable LSST_RESOURCES_HTTP_TEST_SERVER_URL the URL of a server to test against. However, since we are no longer mocking responses, in the current situation we cannot fully test cases where the server does not support some features (e.g. a plain HTTP server, or a webDAV server that does not support download a specified range of bytes).
Checklist
doc/changes