-
Notifications
You must be signed in to change notification settings - Fork 170
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
[policy] implement policy equality and tostring #569
Conversation
cd7f450
to
df10bce
Compare
--- upstream | ||
location /{ | ||
content_by_lua_block { | ||
require('cli') |
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 a bit confused bit this change. A policy chain with { "name": "policy.echo" }
like we had before should still raise a deprecation error, right?
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.
yes in this PR still, but in will need some touches in #566
This test is about prefixing it with apicast
, so this example is more stable than the policies 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.
OK. Didn't think about the implications of this in the other PR.
spec/policy_spec.lua
Outdated
|
||
assert.are.not_equal(p1, p2) | ||
end) | ||
end) |
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.
Nitpick, just for completeness, maybe add a test comparing a policy against itself.
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.
Good one :)
spec/policy_spec.lua
Outdated
end) | ||
end) | ||
|
||
describe('instance equality', function() |
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 can imagine that module equality is useful for comparing policies and loading them, but what's the use case for comparing policy instances?
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 is useful in tests. Like checking that policy is in the chain: https://github.com/3scale/apicast/pull/566/files#diff-b0a6bd0538ae4f76e9bf6a2a045f51beR36
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 this means that two instances of the same policy will be considered to be equal even if they have a different configuration. I think this could be misleading.
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.
True, that is a fair point. But how to solve that? I need to somehow test instances and verifying the configuration would need to use deep equality which is not an easy thing in lua.
But maybe we could check the config just with referential equality and that should be enough for cases I need. But there does not have to be common "config" option, so each policy would have to implement own equality based on properties it sets :/
Thats exactly what you said in #569 (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.
You mentioned that this is only useful in tests.
If you only need this for the specific line that you linked here, I think that using 2 asserts to check version and name is better than introducing this 'dangerous' equality function for instances.
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 we are interested in having module eq but not instance eq, wouldn't it be enough to delete the __eq
entry from this metatable? : https://github.com/3scale/apicast/pull/569/files#diff-b9119890f218a45887b39e830dfc0bb9R43
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.
Yep, but then to compare them we would have to get the metatable and then __index from it to get the module for comparison.
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 that to access the equality method you'll need to do getmetatable(p1.new()).__index._eq
. I don't know if there's a better way to do this.
If this is only going to be used in a test, I'd say it's not that bad. I prefer to have that line somewhere in the tests (as long as it's documented) rather than introduce a dangerous equality function in the codebase. But this is a matter of preference.
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 are right, there can be some helper function in the test to abstract it away.
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.
Resolved by having .policy
property in the metatable. I think that is best of the both worlds. Allows you easily to get the "module" from the instance so it can be compared, but does not rely on existence of __index (that is entirely up the the creator of the policy)
it('shows name and version', function() | ||
local p1 = policy.new('NAME', 'VERSION').new() | ||
|
||
assert.equal('Policy: NAME (VERSION)', tostring(p1)) |
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 looks a bit strange to me because the policy module and the instances have the same string representation.
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.
Yeah, but I have no good ideas how to differentiate them. This is useful when passing them to inspect and there you can kind of see if it is an instance or not.
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.
We could include the config in the instances. Although it might be a very big table depending on the policy.
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.
Hmm now that I think about it, we don't have a self.config
for each policy.
I guess that for now this is good enough. As you said, with inspect we'll be able to clearly differentiate them.
3014c3f
to
d0d4884
Compare
@@ -31,7 +40,7 @@ function _M.new(name, version) | |||
_NAME = name, | |||
_VERSION = version or '0.0', | |||
} | |||
local mt = { __index = policy } | |||
local mt = { __index = policy, __tostring = __tostring, policy = policy } |
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.
@davidor solved it by having a property in the metatable. I think that is best of both worlds.
Implement
__eq
and__tostring
metamethods, soyou can compare policies to see if they are the same.
Also rename
apicast.policy.policy
to correct place:apicast.policy
.Because it is not a policy per se that can be used, but just a "class".