-
-
Notifications
You must be signed in to change notification settings - Fork 108
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
Pogs interfaces #66
Pogs interfaces #66
Conversation
pogs/extract.go
Outdated
@@ -25,6 +25,14 @@ type extracter struct { | |||
nodes nodemap.Map | |||
} | |||
|
|||
var ( |
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.
Don't really need the doc comment.
var clientType = reflect.TypeOf((*capnp.Client)(nil)).Elem()
pogs/extract.go
Outdated
} | ||
client := p.Interface().Client() | ||
if client != nil { | ||
if !val.Type().Implements(clientType) { |
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 you actually want
if val.Type() != clientType {
pogs/extract.go
Outdated
@@ -376,6 +397,15 @@ func isTypeMatch(r reflect.Type, s schema.Type) bool { | |||
case schema.Type_Which_list: | |||
e, _ := s.List().ElementType() | |||
return r.Kind() == reflect.Slice && isTypeMatch(r.Elem(), e) | |||
case schema.Type_Which_interface: | |||
if !r.Implements(clientType) && r.Kind() == reflect.Struct { | |||
field, ok := r.FieldByName("Client") |
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'd like for this to check for a more strict bound:
- Has one field
- That field is called
Client
- That field is of type
capnp.Client
pogs/insert.go
Outdated
default: | ||
return fmt.Errorf("unknown field type %v", typ.Which()) | ||
} | ||
return nil | ||
} | ||
|
||
func getCapPtr(seg *capnp.Segment, val reflect.Value) capnp.Ptr { |
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.
nit: just capPtr
pogs/interface_test.go
Outdated
|
||
import ( | ||
"golang.org/x/net/context" | ||
"testing" |
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.
nit: group stdlib packages apart from others
Base EchoBase | ||
} | ||
|
||
func TestInsertIFace(t *testing.T) { |
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.
Any reason to not add these to the broader table test? I think I have better error handling in there.
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.
Using reflect.DeepEqual on interfaces doesn't really do what we want in this case, and it seemed prudent to have something that tested the behavior of the interface, which would require special casing in the general test anyway. I think at the time I decided making it work would be more disruptive to the existing tests than really made sense. I'm willing to be convinced otherwise.
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've removed reflect.DeepEqual
usage. WDYT 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.
@zombiezen, I think I've addressed everything besides this point. Any thoughts on my comment above?
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.
@zombiezen, ping?
2a89c4c
to
a95b7ef
Compare
Sorry, lost track of this with other stuff. I'll take a look tomorrow. |
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.
Sorry, I forgot I had some comments queued up that I never sent.
pogs/interface_test.go
Outdated
extractedBase := EchoBase{} | ||
err = Extract(&extractedBase, air.EchoBase_TypeID, base.Struct) | ||
checkFatal(t, "Extract", err) | ||
if extractedBase.Echo.Client != nil { |
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 would start the Client off as non-nil and check that it got set to nil.
Base EchoBase | ||
} | ||
|
||
func TestInsertIFace(t *testing.T) { |
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've removed reflect.DeepEqual
usage. WDYT now? 😃
pogs/extract.go
Outdated
@@ -376,6 +391,24 @@ func isTypeMatch(r reflect.Type, s schema.Type) bool { | |||
case schema.Type_Which_list: | |||
e, _ := s.List().ElementType() | |||
return r.Kind() == reflect.Slice && isTypeMatch(r.Elem(), e) | |||
case schema.Type_Which_interface: | |||
if r.Implements(clientType) { |
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 you want r == clientType
here.
So far just Insert, and I haven't tested this; it builds and the existing tests still pass, but I need to get some other work done, so I'm putting it down for the moment.
...and fix a corresponding bug.
This involved factoring out/moving a handful of things to global scope that were previously only visible from inside TestInsertIFace. Still TODO is handling things inside lists; this hasn't been tested and I suspect it doesn't work.
Passes. Note that this adds a type to the aircraft schema.
The only bit left is the question about moving the new tests into the big table, which I need to stare at a bit.
a95b7ef
to
d1ca975
Compare
I think I can make the tests work with the table; I'll have to add a bit of logic to actually call testEcho when the interface is (expectedly) not nil. So it won't be checking for equality really, but that's OK I think. I'll get to this soon. I addressed your other two comments. |
The last of the insert tests is actually failing right now, and thinking about it I'm not sure how it could be made to pass; It's not clear the wire format can represent that.
@zombiezen, I added interface stuff to the main table based tests. It's actually failing currentlly in a case where I'm trying to insert a slice of structs, where some of them have a nil client and some don't; the resulting message ends up with them all filled in. I bet I know what's going on: the composite list wire format can't actually represent lists of structs that have different numbers of pointers filled in, so there's an extra pointer at the end of some of the structs that's being interpreted as a capability pointer. CapNProto doesn't have a notion of a nil/null pointer, just an "absent" one, so I don't think there's a "correct" way to encode a list like this. I'm not sure how to handle this case besides just mentioning in the docs that you can't do that. Thoughts? |
But there is a null pointer for capabilities, this happens all over the place. It's the zero word. That seems like a legitimate failure to me. Any pointer type in Cap'n Proto can be null. |
Ah, you're right -- I missed that reading the spec. I will dig a bit deeper then. |
@zombiezen, fixed. |
I hadn't been aware of this before. This also fixes the test failure; presumably I made some mistake in re-implementing the logic.
Thanks! Sorry this took a while, but I'm happy with how it turned out. |
Cool. No worries about the delays; things come up. |
Addresses #62.
//cc @zombiezen, when you have the time.