Skip to content
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

bug fix for incomplete xml imports #2468

Merged
merged 22 commits into from
Aug 21, 2024
Merged

Conversation

ReimarBauer
Copy link
Member

Purpose of PR?:

Fixes #2456

Does this PR introduce a breaking change?

If the changes in this PR are manually verified, list down the scenarios covered::

Additional information for reviewer? :
Mention if this PR is part of any design or a continuation of previous PRs

Does this PR results in some Documentation changes?
If yes, include the list of Documentation changes

Checklist:

  • Bug fix. Fixes #
  • New feature (Non-API breaking changes that adds functionality)
  • PR Title follows the convention of <type>: <subject>
  • Commit has unit tests

import xml.parsers.expat


def verify_waypoint_data(xml_content):
Copy link
Collaborator

@matrss matrss Aug 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be an ideal use-case for XML Schemas. That would require more than the stdlib xml support though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is currently only a simple solution. A refactoring needs to be done too.

from mslib.utils.verify_waypoint_data import verify_waypoint_data


def test_verify_xml_waypoint():
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to test this specifically or can we cover the entirety of that function by only interacting with MSColab's public interface?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have more than one interface. I want to be sure that this is covered when a refactoring is done and whatever sends us data.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have more than one interface.

And all of them that interact with the real world have to be tested. The important part is that the servers interface to the outside world does indeed do the validation, not that the validation in itself exists and responds as expected.

I just want to emphasize that a test is meant to codify an expected behavior of the code, and the existence of an internal function called verify_xml_waypoint is not a crucial part to ensure for the future, in my opinion.

Ensuring that coverage doesn't decrease through a refactoring could be accomplished by checking that coverage does not decrease, instead.

whatever sends us data

That's the point, this test does not concern itself with if data send from whereever is actually validated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, I first want to know what kind of failures we are aware off. I also want to know that a new function has no failure when it is designed. For me testdriven means to define what the function should solve. The test describes what I had in mind as I wrote the function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure whether this should be discussed on an open channel. However, the XML is never parsed by the server, so the server should be "safe".
The clients are a different matter though. If we think that XML cannot be trusted, simply switching to defusedxml on the client side should solve this...?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joernu76 I think you wanted to respond to #2468 (comment). Yes, you are right, we should take that to a closed channel.

Copy link
Collaborator

@matrss matrss Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me testdriven means to define what the function should solve.

I see that differently. Test-driven means writing tests for the correctness of the change that is to be implemented, in this case for the change that the server and client should verify the xml data. That in the end this function implements the change is an irrelevant implementation detail, as far as testing is concerned IMO. It could be a thousand different functions, and only a single test, as long as the test exercises the change they implement from the codes exposed surface. Testing all of the thousand functions would even be detrimental, because it locks in a particular architectural design, with little to no benefit.

Anyway, no matter if this test is present or not, the client-side validation isn't tested for yet. I.e. I can remove the client-side validation without a test failing.

@ReimarBauer ReimarBauer marked this pull request as draft August 19, 2024 14:26
@@ -179,8 +179,7 @@ def test_delete_operation(self):
assert len(messages) == 0

def _example_data(self):
self.content1 = """\
<?xml version="1.0" encoding="utf-8"?>
self.content1 = """<?xml version="1.0" encoding="utf-8"?>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was also giving an xml.parsers.expat.ExpatError

@ReimarBauer ReimarBauer marked this pull request as ready for review August 20, 2024 10:55
mslib/msui/flighttrack.py Outdated Show resolved Hide resolved
Comment on lines +1981 to +1983
if not verify_waypoint_data(xml_content):
show_popup(self.ui, "Import Failed", f"The file - {file_name}, was not imported!", 0)
return
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the intention is to protect against e.g. maliciously crafted XML or the like, then verification must be the first thing that is done, before using the XML for anything else. In this case though, the XML might be used already here:

model = ft.WaypointsTableModel(xml_content=xml_content)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if function is not None, then that supplied function would need to do the verification as well. But this is a theoretical concern, it seems like for XML files it is always None, and it is only used to provide a way to read CSV files instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a users functions has to return name, waypoints e.g. https://github.com/Open-MSS/MSS/blob/develop/mslib/plugins/io/flitestar.py

How a user can test his functions is a different scope.

self.userdata = 'UV10@uv10', 'UV10', 'uv10'
self.sio = self.sockio.test_client(self.app)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use this as a contextmanager, so it is disconnected properly afterwards.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, actually, I don't think it is useable as a contextmanager, unlike the flask test_client. Still, the disconnect is missing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately context manager protocol is not implemented into the SocketIOTestClient for flask-socketio, but hey I can just use it there where I need it.

@@ -410,5 +443,5 @@ def _save_content(self, operation, userdata=None):
userdata = self.userdata
user = get_user(userdata[0])
fm = FileManager(self.app.config["MSCOLAB_DATA_DIR"])
Copy link
Collaborator

@matrss matrss Aug 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SocketsManager, FileManager and ChatManager instances are only really designed to be singleton objects at the moment; creating more instances of them does not reflect reality, so isn't useful for tests, and might even break stuff as it did with multiple SocketsManagers.

Comment on lines 90 to 95
xml_content = (
(flight_track_with_waypoints, True),
(flight_track_empty, False),
(flight_track_incomplete, False),
(flight_track_with_typo, False),
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pytest-idiomatic way for this would be to parametrize the test over these cases: https://docs.pytest.org/en/7.1.x/how-to/parametrize.html

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, but then the cases outside the function and I don't see that as better readable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they would be outside the function because each case would then actually be a separate test, as far as pytest is concerned. I find it more understandable when it is clear from the failing test itself which case fails, instead of having to look at the test function and figuring out in which loop iteration the assert fails.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separating the tests by different names I can agree but for xml the fixture gets unreadable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added one of the linebreak patterns too, which fails too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next update on the way

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having it split into individual functions with descriptive names like you did looks good too though, pick what you prefer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compared to individual functions in a failure case that would look like

image

How would I see now that flight_track_with_typo was the reason?

Copy link
Member Author

@ReimarBauer ReimarBauer Aug 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we keep it, it is good to have such an examples with more content.

Copy link
Collaborator

@matrss matrss Aug 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh right, it shows the content of the variable as the test name by default. That can be changed with the ids= option to pytest.mark.parametrize.

Copy link
Collaborator

@matrss matrss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The broken encapsulation in the test suite, e.g. by using fm in test_server.py, is a running theme in the entirety of the test suite from what I have seen and I think a refactor to address that is a bit out of scope for this PR.

@ReimarBauer ReimarBauer merged commit 83c6189 into Open-MSS:stable Aug 21, 2024
11 checks passed
@ReimarBauer ReimarBauer deleted the i2456b branch August 21, 2024 13:26
joernu76 pushed a commit that referenced this pull request Aug 28, 2024
* removing pinned xmlschema (#2117)

* Stop ignoring some test files (#2291)

* Reconfigured tutorial videos for RTFD (#2458)

* changed to videos/

* use mss style on rtfd

* fix urls and text (#2460)

* Bump benc-uk/workflow-dispatch from 1.2.3 to 1.2.4 (#2450)

Bumps [benc-uk/workflow-dispatch](https://github.com/benc-uk/workflow-dispatch) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/benc-uk/workflow-dispatch/releases)
- [Commits](benc-uk/workflow-dispatch@v1.2.3...v1.2.4)

---
updated-dependencies:
- dependency-name: benc-uk/workflow-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Limit video width to the containing block's width (#2463)

* pinning of libtiff is not needed but blocks a more recent libxml2 and others (#2469)

* fixed the model.Message description and tests now using op_id (#2470)

* bug fix for incomplete xml imports (#2468)

validate xml content

* prepare v9.2.0 (#2481)

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Matthias Riße <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants