-
Notifications
You must be signed in to change notification settings - Fork 47
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
Initial implementation of GAPIC generator acceptance harness #222
base: main
Are you sure you want to change the base?
Conversation
The debug logger will be switched on by CLI flags later; right now it's hard-coded.
Instead of fetching a relese. This is for the development prepare-to-qualify script.
Capture the language name and options in preparation for running the protoc plugin from this acceptance harness
A Suite is a collection of Scenarios
Also fix a bug where we were not crrectly retrieving files from packr.Box
Need to store files as relative directories
The paths are relative to the scenario dir (in either the source file box or in the sandbox)
protoc still not working
In the future, we'll be able to configure expected failures via a config file, and check for those as well. This also includes miscellaneous documentation improvements.
In the process, constructed a sample config for the echo service and made the hard-coded generator default be protoc-gen-python_gapic via protoc.
This creates a package `qualifier`
This involved refactoring the "run" command so that we can start a server and not block on it ending.
We now officially bundle the acceptance files within the Go binary.
Otherwise we'll trivially succeed on zero checks.
Codecov Report
@@ Coverage Diff @@
## master #222 +/- ##
=======================================
Coverage 99.61% 99.61%
=======================================
Files 13 13
Lines 1036 1036
=======================================
Hits 1032 1032
Misses 2 2
Partials 2 2 Continue to review full report at Codecov.
|
cmd/gapic-showcase/qualify.go
Outdated
ShowcasePort: 7469, | ||
} | ||
qualifyCmd := &cobra.Command{ | ||
Use: "qualify", |
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'm actually reconsidering this command name now. I'm concerned it's not completely obvious what it does. Maybe "check-generator"
would be clearer. WDYT? Other ideas?
If we decide to change it, I can change the package name to match.
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.
check-generator
seems just as vague considering we have several different generators :)
gapic-showcase acceptance
might be another option.
qualify
is pretty good imo, but the usage documentation for the command should be solid & clarify.
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.
check-generator
seems just as vague considering we have several different generators :)
But the usage would have a direct object, like this:
gapic-showcase check-generator python
so it would be clear which generator is being tested.
I don't like acceptance
because it's not a verb.
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.
And good point: I did not have a long usage message. Added.
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.
But the usage would have a direct object
Ah, yes ok then that is reasonable. "check" to me isn't a strong/descriptive enough word. <rhetorical>
What are we checking? That it exists? That it compiles? </rhetorical>
I think "qualify-generator" is a better sounding command because it implies that some sort of validation and comparison of the generator against expected results happens.
Now, digging down into the the "direct object" you mention: is that a sub-command or just an argument? Is it a flag with accepted values (i.e. python, java, go, etc.)? Or free form?
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.
Now, digging down into the the "direct object" you mention
nvm I read the LongUsage, it's an exact arg. Thanks for adding that.
service Echo { | ||
// This service is meant to only run locally on the port 7469 (keypad digits | ||
// for "show"). | ||
option (google.api.default_host) = "localhost:7469"; |
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'm thinking this file should become a symlink to the canonical echo.proto
file, rather than a copy.
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.
+1 I was going to say the exact same thing!
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.
Unfortunately, Packr does not include symlinked files....
I suggest for this PR, we leave this as is: an explicitly copied files. This makes it very explicit what's being tested. Packr does compress the files being included, so additional instances of the file should have just a trivial cost.
If we do become concerned about repeated files as we add to the acceptance suite (for example, if the repeated files get decompressed all at once rather than on-demand), we could look into being able to include showcase API protos via include files. But I suggest we defer that for now.
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'm OK with doing this for now.
additional instances of the file should have just a trivial cost
In this case, I'm not worried as much about size costs but rather maintenance costs. If we add a new annotation or one of the existing annotations changes, or we add a new RPC, we will be updating N echo.proto
files and it is too easy to miss one. It is easy to grow out of sync with multiple copies and then our understanding of what is actually being tested is shaky i.e. we see echo.proto
and assume a lot that might actually no longer be true for an individual copy.
we could look into being able to include showcase API protos via include files
This should be one of the first things evaluated, especially as it might apply to api-common-protos && googleapis/googleapis. Checking in multiple copies of these sources will get out of hand.
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.
To be clear, we already have this for anything under schema/
, but not for the showcase files themselves.
You make a good argument for doing this for showcase files: not having to repeat the modification in all copies. If we don't do it, we'd find out pretty quickly which copies we missed updating because tests would fail---but that's a bad experience. If we do do it, it would make it a lot simpler to update the cases where we expect generation to succeed.
For cases where we expect generation to fail, depending on what we want the error to be, we may want to have copies rather than symlinks so that we can modify them to cause the error we want. For these cases, we may still run into the problem that if a newly required annotation is not present in the previously copied-and-modified file, the error message we get may be due to that instead of the cause we expected, and the test would thus fail. I don't think we can get around that other than by making sure to run the acceptance harness whenever a new annotation comes in, so we can update these cases manually if needed.
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.
For cases where we expect generation to fail, depending on what we want the error to be, we may want to have copies rather than symlinks
That's reasonable. But do they have to be a full copy of a showcase proto (e.g. echo.proto)? Can it just be a minimally working proto with just the one erroneous piece and have it named "gen_failure_{reason}.proto"? If we have 5 copies of echo.proto with entirely the same content except maybe a typo in an RPC name or 1 missing message in order to trigger a failure mode, it will be too easy to assume the wrong thing imo. Does that make sense? I just want the purpose of each added proto/input file to be very clear.
we may still run into the problem that if a newly required annotation is not present in the previously copied-and-modified file, the error message we get may be due to that instead of the cause we expected
Yeah that's fair, it should be obvious when something is missing and a developer should expect to have to update everything in these scenarios.
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.
A couple of things:
-
From previous code reviews I think you mentioned that you disagree with Go naming practices. Most of my comments are WRT naming. I explained the reasoning in my first few comments but eventually opted to just use
s/var1/var2
to save time writing/reading the comments. The reasoning is generally the same. I'm trying to find a middle ground in suggestions, so please be patient with the numerous naming comments. -
I would really prefer that not all of the
qualifier
code be in thecmd/gapic-showcase
directory. Can we move most of the library-oriented stuff to a separate pkg? Ideally thecmd
directory contains CLI/executable style code. -
How big do we expect the acceptance_suite to get? Packing most of
api-common-protos
in the binary is already quite worrisome to me. This could become a lot of static files to pack into the binary...
cmd/gapic-showcase/qualifier/acceptance_suite/basic-check/foo/bar/include.wdREAD
Outdated
Show resolved
Hide resolved
service Echo { | ||
// This service is meant to only run locally on the port 7469 (keypad digits | ||
// for "show"). | ||
option (google.api.default_host) = "localhost:7469"; |
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.
+1 I was going to say the exact same thing!
cmd/gapic-showcase/qualify.go
Outdated
ShowcasePort: 7469, | ||
} | ||
qualifyCmd := &cobra.Command{ | ||
Use: "qualify", |
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.
check-generator
seems just as vague considering we have several different generators :)
gapic-showcase acceptance
might be another option.
qualify
is pretty good imo, but the usage documentation for the command should be solid & clarify.
// Shutdown will immediately start a graceful shutdown of the servers. | ||
func (srv *ShowcaseServers) Shutdown() { | ||
if srv.fb != nil { | ||
srv.fb.Shutdown() // unfortunately, this always results in an en error log |
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'm not sure what you mean here. There is an if
statement that only logs when shutting down fails for some reason.
If when you run your code and it behaves as you describe please file a bug/open a PR to change 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.
OK, I'll do that separately. Not sure whether that print was coming from showcase code or from the http server library.
github.com/hashicorp/go-version v1.2.0 // indirect | ||
github.com/karrick/godirwalk v1.12.0 // indirect | ||
github.com/mitchellh/gox v1.0.1 // indirect | ||
github.com/rogpeppe/go-internal v1.5.0 // indirect |
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.
please remove the indirect
dependencies, these get annoying with RenovateBot and are not strictly necessary
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.
OK, good to know.
And include a README about them
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.
Thanks for the review, Noah! I responded to your comments.
-
naming: I still adhere to the maxim "make your identifier names just long enough to make it easy to read the code, but no longer". I liked a lunch of your suggestions and adopted them, was borderline on others but adopted them, and pushed back on just a few.
-
packaging
I would really prefer that not all of the qualifier code be in the cmd/gapic-showcase directory. Can we move most of the library-oriented stuff to a separate pkg? Ideally the cmd directory contains CLI/executable style code.
Most of the code is in the qualifier
package already. Do you mean moving it elsewhere?
- Size
How big do we expect the acceptance_suite to get? Packing most of api-common-protos in the binary is already quite worrisome to me. This could become a lot of static files to pack into the binary...
The number of checks could grow quite a bit, but they will almost always include just the same files: the showcase protos and the common protos. The nice thing is that Packr compresses the files, so these additional inclusions should not take up extra space in the binary. That said, I'm not sure whether the files get decompressed on the fly or all at once; the latter could be a problem. However, as I mention below, even in that case we can insert the files into the execution sandboxes via include files in the scenarios, so that these files only get packaged/included/decompressed in Packr only once.
In some of the error scenarios we'll check we may well include proto or config files with intentional errors, if we want to test those behaviors, so in those cases we'll have to include those files explicitly. But there will probably be a lot fewer of those, they will be a lot smaller (I'm guessing), and again, if they're repeated in multiple scenarios, we can extend the include mechanism to account for those.
cmd/gapic-showcase/qualifier/acceptance_suite/basic-check/foo/bar/include.wdREAD
Outdated
Show resolved
Hide resolved
cmd/gapic-showcase/qualify.go
Outdated
ShowcasePort: 7469, | ||
} | ||
qualifyCmd := &cobra.Command{ | ||
Use: "qualify", |
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.
And good point: I did not have a long usage message. Added.
github.com/hashicorp/go-version v1.2.0 // indirect | ||
github.com/karrick/godirwalk v1.12.0 // indirect | ||
github.com/mitchellh/gox v1.0.1 // indirect | ||
github.com/rogpeppe/go-internal v1.5.0 // indirect |
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.
OK, good to know.
service Echo { | ||
// This service is meant to only run locally on the port 7469 (keypad digits | ||
// for "show"). | ||
option (google.api.default_host) = "localhost:7469"; |
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.
Unfortunately, Packr does not include symlinked files....
I suggest for this PR, we leave this as is: an explicitly copied files. This makes it very explicit what's being tested. Packr does compress the files being included, so additional instances of the file should have just a trivial cost.
If we do become concerned about repeated files as we add to the acceptance suite (for example, if the repeated files get decompressed all at once rather than on-demand), we could look into being able to include showcase API protos via include files. But I suggest we defer that for now.
cmd/gapic-showcase/qualifier/acceptance_suite/basic-check/foo/bar/include.wdREAD
Outdated
Show resolved
Hide resolved
// Shutdown will immediately start a graceful shutdown of the servers. | ||
func (srv *ShowcaseServers) Shutdown() { | ||
if srv.fb != nil { | ||
srv.fb.Shutdown() // unfortunately, this always results in an en error log |
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.
OK, I'll do that separately. Not sure whether that print was coming from showcase code or from the http server library.
Thank you for meeting me in the middle.
Yeah, I mean moving the
I need to read your suggestions & think a bit more on this one. |
On moving the |
Let's defer, great idea. Don't want to lose all of the history! |
This PR includes most but not all of the needed infrastructure for the acceptance harness, here called "qualifier". It is invoked by
gapic-showcase qualify LANG
(verified withgapic-showcase qualify python
). We will use it to verify generator behavior (particularly in terms of the generated samples) against a running showcase serverFeatures included in this PR:
qualify
, which runs the showcase server in-process in preparation for testing samples against this running servercmd/gapic-showcase/qualifier/acceptance_suite/
**/include.XXX
) to include specific files and whole directories at various levels of the scenario hierarchy--options
to pass additional options to the generator (for example, this is needed for Go but not for Python)To be done in subsequent PRs:
sample-tester
for configured tests of the generated samples running against a live showcase server (right now there is no sample test support)protoc
plugin)To be done in an on-going basis: