-
Notifications
You must be signed in to change notification settings - Fork 58
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
Added tests for createComponent workflow and removed the logs of gradle test #44
Conversation
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.
It seems we've added throws Exception
to every test method whether it's needed or not. If there's a good reason for this, I'd like to learn it! But from my understanding:
- Tests will fail on exception anyway (they are "caught" and "fail" in Junit)
- In some cases there are no exceptions expected
- In other cases we know the type of exception expected
@@ -31,7 +34,7 @@ public String getHostaddress() { | |||
return hostaddress; | |||
} | |||
|
|||
public void getHostaddress(String hostaddress) { | |||
public void setHostaddress(String hostaddress) { |
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 understand this is for test-ability, we do not want to expose this setter as the host address will not change during the lifetime of the extension.
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.
It sounds ExtensionSettings should be immutable, and if that is the case maybe there could be a builder to create objects of a specific configuration for testing?
Note, for tests this can be worked around by creating a mock ExtensionSettings
object that returns the expected values.
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 a good call out. Removed setters and found a way ObjectMapper can initialize in the constructor.
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.
Most of the changes look good.
Just a tiny comment. Thanks @owaiskazi19 for these changes!
@@ -19,30 +19,26 @@ public class ExtensionSettings { | |||
// Change the location to extension.yml file of the extension | |||
public static final String EXTENSION_DESCRIPTOR = "src/test/resources/extension.yml"; | |||
|
|||
public String getExtensionname() { | |||
return extensionname; | |||
public ExtensionSettings(String extensionname, String hostaddress, String hostport) { |
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 generally like the use of a constructor like this to set the fields, but this also implies these will always be the only fields we'll be using. If we add one more we'd have to create a 4-arg constructor but because of SemVer we couldn't delete the 3-arg one; we could deprecate it but then we'd have to deal with what the appropriate default is etc.
All this is to say that this is only a good idea if we are absolutely sure these are the only 3 fields we will ever likely have in this class.
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.
Actually, this is the way of initialization required by ObjectMapper to load yml file and the other was using setters but since we don't want to expose or modify host address and port, this is the approach I went for. Open to suggestions though.
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.
Hard-coding inputs (as in constructors) is nearly always disconnected both logically and programmatically from reading in an arbitrary number of configurations key/value pairs via an external file.
This is an interesting use case in that we want a POJO which is what we currently have but we also want to reserve the right to later generate a different POJO with more fields.
I took a look at ObjectMapper docs and it seems that it uses reflection and you can actually use private constructors for this purpose. That may help settle the SemVer argument as it is obvious non-API. Alternately if there is some way we can mark this class as "internal" (a package with internal in the name is the common approach) then we also aren't bound by SemVer.
So the approach may be correct but the file location may not be. We need special treatment (package location) for these POJO objects.
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.
As discussed. Removed the arg constructor and called super for no arg constructor
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 we need a bit more clarity on exactly what Jackson's expectations are for deserializing. I'm not sure what the correct implementation is, but I'm skeptical the current state is it.
…le test Signed-off-by: Owais Kazi <[email protected]>
Signed-off-by: Owais Kazi <[email protected]>
Signed-off-by: Owais Kazi <[email protected]>
Signed-off-by: Owais Kazi <[email protected]>
Signed-off-by: Owais Kazi <[email protected]>
/** | ||
* Jackson requires a default constructor. | ||
*/ | ||
private ExtensionSettings() { |
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.
How does ObjectMapper
use this?
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.
How does
ObjectMapper
use this?
Reflection!
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.
It uses reflection to fill the attributes with the value present in the yml file
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.
Which introduces its own problems with Java Modules, if we ever decide to publish a module descriptor we'll have to open this package to Jackson's module. But for now, let's enjoy the classpath...
public void testRegisterRequestHandler() { | ||
|
||
extensionsRunner.startTransportService(transportService); | ||
verify(transportService, times(3)).registerRequestHandler(anyString(), anyString(), anyBoolean(), anyBoolean(), any(), any()); |
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.
Instead of any
, lets verify the respective handlers are being registered.
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.
When we invoke startTransportService
above it expects all the 3 handlers to be present at the same time. If we try to match it one by one, it causes MatchersException. I tried this before using any
. I'm open to suggestions
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 I didn't understand it. Why does it expect all 3 handlers at the same time?
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.
As startTransportService is registering all 3 handlers
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 sure there is a way. I dont want to block this PR for this one.
See if you find a solution.
); | ||
PluginRequest pluginRequest = new PluginRequest(sourceNode, null); | ||
PluginResponse response = extensionsRunner.handlePluginsRequest(pluginRequest); | ||
assertEquals(response.getName(), "RealExtension"); |
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.
Not for this PR, but can you open up a follow up issue to respond back with the name we get from extensions.yml
instead of static RealExtension
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 covered it in this PR itself
|
||
extensionsRunner.sendClusterStateRequest(transportService); | ||
|
||
verify(transportService, times(1)).sendRequest(any(), anyString(), any(), any()); |
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.
Same as above, lets actually verify the params are what we expect.
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.
Tried to match it with the Handler class
|
||
extensionsRunner.sendClusterSettingsRequest(transportService); | ||
|
||
verify(transportService, times(1)).sendRequest(any(), anyString(), any(), any()); |
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.
You know my 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.
LGTM with the note that we should track the YAML file location in another issue.
/** | ||
* Jackson requires a default constructor. | ||
*/ | ||
private ExtensionSettings() { |
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.
Which introduces its own problems with Java Modules, if we ever decide to publish a module descriptor we'll have to open this package to Jackson's module. But for now, let's enjoy the classpath...
Signed-off-by: Owais Kazi <[email protected]>
Signed-off-by: Owais Kazi <[email protected]>
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.
Thank you @owaiskazi19 for this PR!!
Thanks @saratvemulapalli and @dbwiddis for the thorough review. |
…le test (opensearch-project#44) * Added tests for createComponent workflow and removed the logs of gradle test Signed-off-by: Owais Kazi <[email protected]> * Addressed PR Comments Signed-off-by: Owais Kazi <[email protected]> * Removed setters to avoid accessing extension attributes Signed-off-by: Owais Kazi <[email protected]> * Created ObjectMapper object to test the extenions.yml Signed-off-by: Owais Kazi <[email protected]> * Naming style Signed-off-by: Owais Kazi <[email protected]> * PR comments Signed-off-by: Owais Kazi <[email protected]> * Removed static extension name Signed-off-by: Owais Kazi <[email protected]>
Signed-off-by: Owais Kazi [email protected]
Description
Added tests for createComponent workflow, ExtensionsSettings and removed the logs of gradle test
Issues Resolved
Part of #25 and closes opensearch-project/OpenSearch#3082
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.