Related to that, how do I specify a proto message ...
# protobufs
s
Related to that, how do I specify a proto message field that must be non-nil, but I don't particularly care about it's fields? According to this doc: https://docs.pact.io/getting_started/matching/gotchas#an-empty-hash-in-the-response-means-allow-any-hash - any content is valid for that field, and that includes nils, but in some cases I care that e.g.
GetUserResponse
contains non-nil
user
field and nil
error
field, but it's probably not ok if both are nil (but it's likely ok if both are non-nil)?
r
The only thing I can think of is to try match the empty string (there is no nil value in Protobuf).
s
there's no nil for primitive values, but message fields can be nil, can they not?
r
No, they will have the default value for the type.
s
interesting. When using go protobuf implementation, message fields can be nil. Their accessor methods are nil-safe though, so you can do smth like:
Copy code
user, err := userService.GetUser()
// skip err
if user == nil {
   // user itself can be nil
   // but user.GetID() would return default value
   user.GetID()
}
I do see in some of our services we do have nil checks for message fields. Is it implemented differently in rust?
here's the generated protobuf code for primitive type in go (default value is not nil):
Copy code
func (m *User) GetEmail() string {
	if m != nil {
		return m.Email
	}
	return ""
}
and here's one for the message type (default value is nil):
Copy code
func (m *User) GetCreated() *types.Timestamp {
	if m != nil {
		return m.Created
	}
	return nil
}
r
Oh, that's the message itself that's nil. In Rust it will use an optional enum (there is no nil value in normal safe Rust code).
s
how hard would it be to add a notEmpty/notNil support for the message itself? Like I naively tried smth like:
Copy code
"msg": {
    "pact:match": "notEmpty($'_msg_template')",
    "_msg_template": {
          "username": "matching(type, 'user')",
// etc
     }
}
but it didn't work (of course)
I've also tried
"msg": "notEmpty()"
to hopefully just trigger the non-nil check, but its also not supported
r
Normally, if you define the expected structure, it will be an error if the value is not present, so there is no need for an explicit rule
The issue is with the error condition (where it should not be present). There is no way to do that.
s
> Normally, if you define the expected structure, it will be an error if the value is not present, so there is no need for an explicit rule that's not what I've experienced. I had a structure defined in my matchers, the server didn't send the value and the provider test was still successful, e.g. if my rpc is defined like:
Copy code
message GetUserReply {
  User user = 1;
  Info info = 2; 
  Data data = 3;
  Error error = 4;
}
and I have matchers defined on all the fields, and the server responded with a message where
User
is defined but data, info and error are nil, the provider test still passed. I'll try to provide a reproducible case some time this week.
like any of these fields can be nil, but would match successfully, unless I use
notEmpty
for some fields inside e.g.
user
r
Hmm, that is surprising. Must be a regression.
s
i'm also not sure if my pact-ffi lib is the most recent or not; I'll try to come up with an easy reproducible scenario later this week