-
Notifications
You must be signed in to change notification settings - Fork 449
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
Refactor Python testing scripts and utilities - Part 1 #3855
Conversation
fruffy
commented
Jan 23, 2023
- Replace the custom defined "outputs" with an actual logger that prints and logs to a file as needed
- Use modern Python3 code (f-strings, pathlib, etc)
- Use subprocess.run instead of opening a process than running it.
685147d
to
492d22b
Compare
@vlstill This is a big PR, because it refreshes a lot of the old Python code. Still, among others, it refactors the test utilities to use After this PR, I am planning to generalize ebpfenv, such that it can be used as a general virtual namespace environment. Finally, add typing information to all the Python utilities. You had some comments on the PTF PR, are those resolved or do you have any other suggestions? |
@mbudiu-vmw This PR makes a lot of changes in the testutils library and migrates to actual logging for the test scripts from the custom logging that we had. It does not touch the Python scripts which do not depend on testutils, such as @tatry @osinstom This PR touches ubpf scripts, too. Any dependencies I should keep in mind there? |
import random | ||
import logging |
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 will let the owners of this file review the changes
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.
That's us! We approve :)
backends/bmv2/run-bmv2-test.py
Outdated
try: | ||
result = process_file(options, argv) | ||
except Exception as e: | ||
print("Exception ", e) | ||
sys.exit(FAILURE) | ||
print(f"There was a problem parsing STF file {options.testFile}:") |
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 is this always a parsing problem?
backends/ebpf/run-ebpf-test.py
Outdated
# Actual location of the test framework | ||
self.testdir = os.path.dirname(os.path.realpath(__file__)) | ||
self.extern = "" # Path to C file with extern definition | ||
self.binary = "" # This program's name. |
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 find the original version easier to read. Why spend time reformatting whitespace?
import sys | ||
from pathlib import 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.
is this file even used?
import sys | ||
from subprocess import Popen, PIPE | ||
import logging |
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 will let the owners review this file
@@ -40,7 +40,8 @@ p4tools_add_xfail_reason( | |||
|
|||
p4tools_add_xfail_reason( | |||
"testgen-p4c-bmv2-ptf" | |||
"Invalid reference to object of type" | |||
"Segmentation fault" |
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.
This is not a good sign.
I see no reason for the changes in the test scripts to lead to a segfault, something must be wrong somewhere.
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.
In both cases the segmentation fault is thrown.
The underlying cause is a bit tricky. Previously, simple_switch_grpc was invoked with --log-console, which directly printed output to stdout/err. However, this occasionally overwhelmed the process pipe and the process got stuck.
Now, we use --log-file
, but simple switch crashes before the statement can be logged/generated. So it does not appear anymore.
The completely solution is to either fix simple_switch's logging or to fix the Popen call so that it does not get stuck.
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.
If it's the same bug please file an issue and add a comment to the makefile.
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 believe it is this bug https://github.com/p4lang/behavioral-model/issues/1124
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 am not aware of a corresponding bug for p4c, we should have one. Can you please add one?
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 asked Antonin to migrate the issue.
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 was trying primarily to look at the Python side of the change, I did not check overall design. I think this goes in the right direction and I have a few suggestions in the code.
I'd suggest running the code through some python formatting checker such as pycodestyle
and possibly through flake8
(linter). I think that for languages that have specified code style, it generally makes sense to adhere to it (even though I might personally disagree with some python style decisions).
FILE_DIR = Path(__file__).resolve().parent | ||
TOOLS_PATH = FILE_DIR.joinpath("../../tools") | ||
sys.path.append(str(TOOLS_PATH)) | ||
import testutils |
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 add a comment that this import needs the path modification?
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.
Really dislike this boilerplate code actually. Do you have a better idea how to handle relative parent-level imports? Without requiring the user to input the path every time.
return partial(self.func, instance, *(self.args or ()), | ||
**(self.keywords or {})) | ||
return partial(self.func, instance, *(self.args or ()), **(self.keywords or {})) |
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.
This (and similar changes) now goes over the 79 character limit of Python's formating conventions. I don't think that is a good idea, many (at least semi-intelligent) code editors will highlight that as a problem. If we want to go against some of the python style guides, I think we should have an override file that informs pycodestyle
and similar programs what is to be ignored.
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 have been using a .yapf.style
and a .pylintrc
file with a character limit set to 100. I used 100 because our C code also uses 100 as character limit. I can add this file and its formatting in a separate PR?
I have been not using black since it is a little too opinionated. There are so many options for style tools, I am actually not sure which we should use.
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 see. Is there any reason to not add the style config files in this PR?
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.
This PR is already big, so I was hoping to do the formatting in a separate PR. Then we can also agree on a style there.
@@ -246,22 +248,19 @@ def __exit__(self, exc_type, exc_value, tb): | |||
if not issubclass(exc_type, P4RuntimeWriteException): | |||
# let unexpected exceptions pass through | |||
return False | |||
self.exception = exc_value # store for later retrieval | |||
self.exception = exc_value # store for later retrieval |
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.
Again, this was formatted according to the python style guide (at least two spaces before comment) and now goes directly against 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.
Having formatting that complies with Mihai's request and the two space rule is unfortunately quite difficult. I have not been able to find a configuration that does both (Aligning comments as well as maintaining a minimum distance).
Personally, I prefer to have no inline comments at all since they often run over the maximum character length.
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.
This is the issue I am facing. But other formatters are also not better at this. It might be less headache to forbid inline comments in general.
backends/bmv2/bmv2stf.py
Outdated
def ByteToHex(byteStr): | ||
return ''.join( [ ("%02X" % x) for x in byteStr ] ) | ||
return ''.join([("%02X" % x) for x in byteStr]) |
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.
return ''.join([("%02X" % x) for x in byteStr]) | |
return ''.join(("%02X" % x) for x in byteStr) |
(join can accept an iterator expression directly)
backends/bmv2/bmv2stf.py
Outdated
@@ -249,13 +282,14 @@ def makeMask(self, value): | |||
value = value[2:] | |||
prefix = "0o" | |||
else: | |||
raise Exception("Decimal value "+value+" not supported for ternary key") | |||
raise Exception("Decimal value " + value + " not supported for ternary key") |
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.
or
raise Exception("Decimal value " + value + " not supported for ternary key") | |
raise Exception(f"Decimal value {value} not supported for ternary key") |
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 have not touched bmv2stf.py yet except for a little formatting. The code is very old and written for Python 2.7. I would like to do this in a separate PR.
backends/ebpf/targets/target.py
Outdated
# If the compiler crashed fail the test | ||
if 'Compiler Bug' in open(self.outputs["stderr"]).readlines(): | ||
sys.exit(FAILURE) | ||
if "Compiler Bug" in str(out): |
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.
is out
binary?
return proc | ||
|
||
|
||
def run_process(verbose, proc, timeout, outputs, errmsg): | ||
|
||
def run_process(proc, timeout, errmsg): |
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 name is a bit misleading, it suggest the process is executed, but in fact only its outputs are consumed.
@fruffy it's been a while since we worked on the uBPF backend, but there should not be any specific dependencies to be aware of. |
770b0b2
to
20143f1
Compare
20143f1
to
ece0074
Compare
@mbudiu-vmw Any concerns on your side that have not been resolved yet? |
This is not my favorite part of the compiler, so I try to avoid it. If you promise to take care of it, it's yours. |
Thanks! A lot of the code that was touched in this PR I have written at some point, so I am on the hook anyway. |