tjones
2021-08-23 11:28
has joined #libpact_ffi-users

matt.fellows
2021-08-23 11:28
has joined #libpact_ffi-users

mike.geeves064
2021-08-23 11:36
has joined #libpact_ffi-users

mike.geeves064
2021-08-23 11:37
:wave:

tjones
2021-08-23 11:37
:wave: Welcome!

mike.geeves064
2021-08-23 11:37
Thanks :slightly_smiling_face:

mike.geeves064
2021-08-23 11:38
Good idea, I was using bits of conversations in various places

tjones
2021-08-23 11:38
I'm hoping this will be a good way to reduce re-discovery as people work with the ffi bindings

tjones
2021-08-23 11:38
Mee too :slightly_smiling_face:

tien.xuan.vo
2021-08-23 11:39
has joined #libpact_ffi-users

tien.xuan.vo
2021-08-23 11:39
:wave:

tjones
2021-08-23 11:43
Welcome!

mike.geeves064
2021-08-23 11:43
For sure! Matt and Ron especially must be quite tired of pasting the same links over and over :D

tjones
2021-08-23 11:44
haha! Yes

tjones
2021-08-23 11:44
We have the libpact_ffi verifier working end to end for pact-js (not released yet)

mike.geeves064
2021-08-23 11:45
Is there a "list" of current questions outstanding etc or just see what comes in?

tjones
2021-08-23 11:46
I'm not aware of one - we're about to do the consumer bindings for pact-js

tjones
2021-08-23 11:46
which I'm sure will generate questions

tjones
2021-08-23 11:46
also maybe one outcome from having this channel might be some getting started documentation

tjones
2021-08-23 11:47
The header files have quite a bit of documentation in them, but I didn't realise that to start with.

mike.geeves064
2021-08-23 11:48
Nice I've been having a play with python but seem to be starting with trying to add to rust :thinking_face: Have you used the pactffi_string_delete function? On my to-do list to add in before going too far

tjones
2021-08-23 11:48
I haven't, because we don't currently get any strings back from the ffi.

tjones
2021-08-23 11:48
but yes, it seems important


tjones
2021-08-23 11:49
this is the verifier bound to JS. Interesting bits might be: The mapper for the options to the CLI args that get passed in to the FFI binding: https://github.com/pact-foundation/pact-js-core/blob/master/src/verifier/arguments.ts


tjones
2021-08-23 11:50
Also this might be directly useful - it downloads the libs for each arch: https://github.com/pact-foundation/pact-js-core/blob/master/script/download-ffi.sh

mike.geeves064
2021-08-23 12:41
So, on the python side there is a python install_ffi_app function which will go and get them. From a DRY pov, it could make sense to have for example a sh script like that in pact-reference and then say from the python Makefile just grab and execute that instead. Here seems like a good place to start with asking other people from their respective languages as well if they think that would be a good idea :slightly_smiling_face:

mike.geeves064
2021-08-23 12:44
What did you think of the idea I posted in #pact-rust about trying to just expose as much as possible including data types via an FFI call?

kyle.florence
2021-08-23 13:28
has joined #libpact_ffi-users

andrew.patterson
2021-08-23 13:55
has joined #libpact_ffi-users

pact544
2021-08-23 14:07
has joined #libpact_ffi-users

tjones
2021-08-23 14:12
Oh, I haven't seen that! I'll check it out tomorrow - please feel free to hassle me if I don't report back

tjones
2021-08-23 14:14
The experience from pact-js is that pact users can be behind all manner of corporate firewalls / proxies, so bundling with the library for installation through the package manager is a much nicer experience. Of course, that doesn't work for all ecosystems - go, for example, I think enforces that libraries are only go code.

mike.geeves064
2021-08-23 14:23
Oh, I mean for the scripts to build from source rather than distribution if that's what you mean? As in when you do a "make package" it will currently call the python function to download the libs from pact-reference, I'm suggesting it could be: 1. Makefile downloads the script which downloads the libs from pact-reference, 2. Run that script to download libs from pact reference Rather than just: 1. Makefile runs the python (or other code) to download the libs from pact-reference Agreed about corp firewalls for end users

mike.geeves064
2021-08-23 14:26
Currently bemusing myself a little as after the "can I help with contributing some python code" my first two steps have been ? Here's some rust code, could we do this so I don't have to write python ? What about we don't write that in python and user a shell script so I don't have to write that in python I can do python Dev, honest! :joy:

matt682
2021-08-23 15:41
has joined #libpact_ffi-users

uglyog
2021-08-23 22:55
has joined #libpact_ffi-users

matt.fellows
2021-08-23 23:23
:wave:

matt.fellows
2021-08-23 23:23
thanks Tim - it was definitely time!

tjones
2021-08-23 23:52
> Makefile downloads the script which downloads the libs from pact-reference, I'm nervous about doing "download this script then run it" in CI. I've been thinking about writing some automatic actions for pact-js to do things like making sure that some boilerplate files (eg CONTRIBUTING.md) are in sync across all the JS repos - perhaps something like that would work here? Also, I'm sure keeping boilerplate in sync across several repos must be a common problem with some nice solutions

mike.geeves064
2021-08-24 00:14
In sync would probably better, I know what you mean about nervous running some "unknown" script (I'm assuming pact-reference repo would have a bit more oversight etc than in general, but still a fair point) I haven't looked into repo level sync :thinking_face: I was wondering about trying cookie cutter (python) to be able to re-apply a template to do something like that. I don't think any of the people I have worked with have fine across a good solution, given the state of many code bases :joy:

mike.geeves064
2021-08-24 00:17
:thinking_face: thinking CI, you could lint style warn if some files are out of sync at least

mike.geeves064
2021-08-24 00:18
Possibly this is where the monorepo answer comes in :)

mike.geeves064
2021-08-24 00:30
[also re the nervous downloading and running, you could ofc have the expected checksum etc of the file to make sure it doesn't change unexpectedly... But maybe at that point for something relatively simple it is back to more comfortable to just maintain when needed :thinking_face:]

tjones
2021-08-24 01:29
> Possibly this is where the monorepo answer comes in :slightly_smiling_face: Yeah. JS doesn't have any really nice solutions for monorepo - there's a pretty well liked tool called lerna, but I believe that requires yarn, and they've been doing some weirdly opinionated things that break dependency management because they disagree with the way npm works. Which is... fine academically, but not helpful in practice.

mike.geeves064
2021-08-24 09:11
"Creating a default community health file - GitHub Docs" https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file this looks promising for the original use case you mentioned, I haven't tried it yet to see what it does exactly, if it uses then only on creation of automagically has them there, I'm sure GitHub could display then when viewing the repo if they aren't actually committed to the repo itself but I'm not sure how it could work when you pull it, and you probably want it visible in the actual repo

mike.geeves064
2021-08-24 09:12
At risk of going OT from FFI already :)

tjones
2021-08-24 13:56
Oh, that's awesome!

tjones
2021-08-24 13:56
Thanks

tjones
2021-08-25 07:43
Has anyone got the ffi libs working on windows yet?

tjones
2021-08-25 07:43
How did you do it?

tjones
2021-08-25 07:44
oh wait! I did it!

matt.fellows
2021-08-25 07:46
I?m _assuming_ one of the Pact .NET people did. It?s fair to assume most .NET people still use Windows, right?


tjones
2021-08-25 07:53
I think this might actually pass

tjones
2021-08-25 07:53
wait, this isn't a PM with matt. Apologies everyone!

tjones
2021-08-25 07:54
For those playing along at home, you need `.dll` not `.dll.lib`. From the error messages, I suspect that `.dll.lib` is for 32 bit? I am not sure.

tjones
2021-08-25 07:54
That seems likely

matt.fellows
2021-08-25 07:55
:laughing:

matt.fellows
2021-08-25 07:55
it?s best everybody sees how the sausage is made Tim

mike.geeves064
2021-08-25 09:26
Any thoughts? As with the other discussion on the .sh files, no point in progressing if it's considered a bad idea, I'm happy either way but especially since I've not actually "contributed" anything yet I'm a little wary of doing too much without input on good/bad direction :slightly_smiling_face: I didn't actually get the data type part going yet (although maybe that's not so important), works pulling out the args, defaults [e.g. http], allowed values [e.g. log]. Although a different route could be that since clap supports pulling in the config from a yaml, maybe that could be a better starting point than deconstructing afterwards :thinking_face:

tjones
2021-08-25 09:46
Largely it looks like a good idea! I like the idea that it will possibly simplify / genericise implementation. I'm not sure it would work for all cases (we can't easily, for example, generate the typescript types for it from the binary - although maybe we could make tooling that could)

tjones
2021-08-25 09:48
I think there might be some work on getting the ffi verifier going in Python already - I think I remember seeing @elliottmurray talking about it some time

elliottmurray
2021-08-25 09:48
has joined #libpact_ffi-users

tjones
2021-08-25 09:49
> a little wary of doing too much without input on good/bad direction I'd say anything that makes it easier to get value into user's hands is a good thing. The question for me would be how much easier would it be with the proposed interface vs the current one

tjones
2021-08-25 09:51
In the case of the verifier, if you look at the mapping code I linked earlier, it's not actually a lot of work to map it without helpers. However, the work that we did there will have to be re-implemented in the other languages each time. Of course, if we had a generic interface, a mapping is still necessary, but it might be simpler? I don't know.

tjones
2021-08-25 09:51
Do you have a specific thing you want to contribute, or just "I'd like to help out"?

tjones
2021-08-25 09:55
(I probably have different guidance depending on the answer there)

tjones
2021-08-25 09:56
Of course, as with any open source project, the main answer is "work on something you'd enjoy working on" and "yes please, we'd love extra contributors"

mike.geeves064
2021-08-25 10:21
Thanks for replies :slightly_smiling_face: So I'm looking at python mostly [most comfortable language of choice] - have already briefly spoken to Elliott who suggested taking a look at the FFI stuff. I just started getting distracted with Rust early on :smile: My area of expertise is generally going off on tangents while looking to improve CI/CD, processes etc. Largely happy to help with whatever, long time in a closed corp environment, seemed like time to try and "give something back". The original purpose right now was because I wanted to do event testing of some AWS code I'm working on and it wasn't possible in python yet, but I think Elliott has recently made progress with that against the previous spec implementation. Yeah, generating the types was going to be a next [in a few steps time] step to look at, I'm not quite sure how to nicely do that on the python side yet either. I'm thinking there might not be an easy way to create them directly but it could always be a step when retrieving the FFI libs themselves via script or code during packaging to generate *something*. I like things that write themselves, but opinions vary on keeping it pure vs kind of a hack, hence question of does anyone else like the concept :slightly_smiling_face: For example [very quick google search, could be a non starter], https://github.com/cwacek/python-jsonschema-objects this looks like it could work to get a bit of JSON [which would come from FFI, maybe with a bit of mangling] that could be grabbed at package time, and then use that for creating your object with typing For the CLI part, since it's just "dumbly" calling the binary with the args more or less, it looks fairly simple for the wrapper, but there's still the actual verifier to look at directly which will probably be tricker!

mike.geeves064
2021-08-25 10:24
For sure not much work to map it, it's the ongoing has anyone noticed that something has changed and now that needs updating across the various languages, as with the contributor.md example where you have the...and why is it ever so slightly different over here that I'm thinking about

mike.geeves064
2021-08-25 10:38
Ah, or like this for typescript [again, quick google search, may be no good] https://quicktype.io/typescript - from a maintainer pov I think I would be more comfortable with a flow of download an updated external lib and then be able to see in an e.g. generated json file in the repo that something has changed from last time, than hoping my tests cover sufficiently a potentially fragile link to a lib and having to figure out why it now segfaults

uglyog
2021-08-25 23:13
On Widows, `.dll.lib` is a static library that contains all the code to load the shared library `.dll`

uglyog
2021-08-25 23:14
With languages like C/C++ and .Net, you probably need both

tjones
2021-08-26 04:10
hmm... it worked ok in CI with only .dll

tjones
2021-08-26 04:10
maybe the tests aren't fully functioned

tjones
2021-08-26 04:10
(the node ffi bindings pretend it's C)

uglyog
2021-08-26 04:34
Node can deal with just the `dll`

mike.geeves064
2021-08-26 10:55
Ok so, I've made a couple more changes to the FFI method to pull out the Rust CLI args: https://github.com/mikegeeves/pact-reference/pull/1/files#diff-0683cbee93e01f96b27383c0954421fc5be638947d54311f880ba9b84ba2cb61 - that seems to be complete enough for me to construct the CLI args on the python side (the only missing bit is types to identify an int or str, I didn't see how to cleanly pull out something from the validator but I think that's ok to skip for now). Does that look helpful for use elsewhere? I'll wait a bit then hit the PR button :slightly_smiling_face: > $ pact-verifier --help > Usage: pact-verifier [OPTIONS] > > Options: > --enable-pending Enables Pending Pacts > --disable-ssl-verification Disables validation of SSL certificates > --publish Enables publishing of verification results > back to the Pact Broker. Requires the > broker-url and provider-version parameters. > > <snip> > --scheme [http|https] Provider URI scheme (defaults to http) > -p, --port TEXT Provider port (defaults to protocol default > <snip>

mike.geeves064
2021-08-26 10:58
The Rust change would largely be redundant if using clap from yml config which could be shared around instead, but that doesn't look like it supports validators. Types are hard :slightly_smiling_face:

edanielsen
2021-08-26 11:08
has joined #libpact_ffi-users

edanielsen
2021-08-26 11:09
*tsk* *tsk*

pact544
2021-08-26 19:25
Nah .Net just needed the `.dll` not the `.lib` as well

pact544
2021-08-26 19:26
You bet your bottom dollar we do :smile:


pact544
2021-08-26 19:30
And we also bundle those inside the NuGet packages that PactNet generates, then it'll extract the appropriate one for your arch/OS when you install the dependency

tjones
2021-08-27 01:30
I'm afraid I don't (yet) read rust, so I can't tell very easily. If this is what we talked about earlier, yes it sounds useful.

mike.geeves064
2021-08-27 07:19
It is yep. That's ok I don't write rust as such either :thinking_face:

mike.geeves064
2021-08-27 09:03
Hitting the big red button after adding a test

mike.geeves064
2021-08-27 09:04
Memory management and pointers etc scare me :open_mouth:

mike.geeves064
2021-08-27 13:57
Ohh, I forgot envs, but no more time right now :thinking_face:

mike.geeves064
2021-08-27 15:16
[added :D]

mike.geeves064
2021-08-28 12:52
Following on from half a conversation with @pact544 about output from the FFI lib, could something like slog-json be useful, rather than stdout style logging from fern? Something structured could then mean less mangling on the python/net/js etc side, which can be quite brittle if doing anything other than passing straight through. There seems to be some JSON output as well sometimes but not quite sure exactly when/why/how, I need to look through the code. Not sure if that's all in progress, already considered etc, any thoughts @uglyog / anyone else on how they are planning on working with/using the output :slightly_smiling_face:

uglyog
2021-08-28 23:59
:man-shrugging: I don't have any opinion either way. What ever works to make it easier for users to be able to provide information to diagnose issues.

tjones
2021-08-29 02:46
There's also this, which I'm planning to bring the rust library in line with: https://github.com/pact-foundation/pact-specification#logging-in-a-pact-library

mike.geeves064
2021-08-29 08:01
Tim: I couldn't see anything by that other than "tldr: make sure logging levels are correct" (which absolutely makes sense, I think info when the pact test fails but not the lib/usage is an important distinction to clarify, for example :+1:)

mike.geeves064
2021-08-29 08:04
Was that it or did I miss something? :slightly_smiling_face:

matt.fellows
2021-08-30 04:28
Tim?s put together some notes about what we *should* be logging at each level, and the purpose of log levels for the framework

matt.fellows
2021-08-30 04:29
if everyone agrees on the terminology and meaning of a `debug` log, then we can more confidently create useful end-to-end experiences (i.e. have the client and rust libraries use the same meanings for each of the log levels,)

matt.fellows
2021-08-30 04:30
but yes, basically those kinds of distinctions is the point

matt.fellows
2021-08-30 04:30
it?s separate from fixing the logging itself, so that we can more usefully present them to users

tjones
2021-08-30 06:35
Yep. I was mentioning it as a side point, since we're talking about logging and making the logs available to different frameworks

tjones
2021-08-30 06:36
btw, what we're planning to do in pact js is to defer all logging to rust.

tjones
2021-08-30 06:36
this is fine, because in js land people expect logs on standard out

tjones
2021-08-30 06:36
it won't work for ecosystems like .NET though.

tjones
2021-08-30 06:37
and structured output lets us do lots of nice QoL things - like "hey, you're missing state change definitions for these states, here's a template you can paste into your code"

matt.fellows
2021-08-30 06:41
I'm not sure of the value of structures log output, I haven't thought too much but that's a good example

matt.fellows
2021-08-30 06:42
Structured verifier output though would be preferable, separate to structured logs

matt.fellows
2021-08-30 06:42
I like having a consistent way to show verification results - that will make docs much easier ("here's how to interpret verification failures")


mike.geeves064
2021-08-30 11:00
Yeah that's what I was thinking, around the filtering. If you've got the structured log output it's then much easier (at least less brittle) to for example filter out the content relevent to verification logs. Especially if that's going to be info level rather than error for example (I think info does make the most sense) If it's a structured log you can then use the language native functionality to filter and say stream the info logs of type verification out to a file and error logs to stdout and so on, as well as being able to have a more language consistent user experience if it 'looks like python logs" Architect hat on here, I can see a few user cases where it could be beneficial, at least imo, but if it wouldn't be seen as valuable across various languages then it's over engineering

mike.geeves064
2021-08-30 11:01
:100: for consistent terminology etc, principle of least surprise

mike.geeves064
2021-08-30 11:06
? I would definitely go for Tim's guidelines on making the log levels consistent ? If a structured log output is desired it would be effective looking at both together I think, e.g. if something was an ERROR and now it's an INFO, it's a good time to make sure you have e.g. a way to distinguish it from "just letting you know" (easier than doing later)

pact544
2021-08-30 11:32
Yeah I think the main thing I've found with the consumer logs we have is that they're very Rust-like. There's lots of `dbg!` style output where it'll say things like `header: Some(Header::ContentType("application/json"))`. That's kinda fine for me because I know Rust, but to someone who primarily does C# that's all a bit weird. Those aren't the types of things you're expecting to see to help you work out why your test is failing. Its good for debugging the Rust code itself, but I'd prefer a more human-readable style to display to users in the general case, and perhaps a flag or log level which enables the very Rust-specific output for cases where we think it's a genuine bug in Pact rather than a user's test failing properly.

mike.geeves064
2021-08-30 11:33
Especially if people have only just got the hang of what ruby output looks like :grinning:

matt.fellows
2021-08-30 11:34
that should be `trace` based on Tim?s output

matt.fellows
2021-08-30 11:34
trace == for maintainers

matt.fellows
2021-08-30 11:34
debug == for users to be able to debug the problem

matt.fellows
2021-08-30 11:34
but probably the use of `dbg!` is not good anyway

mike.geeves064
2021-08-30 11:34
Hopefully the bug in pact should be covered by error with failing pacts as info, but there's going to be quite a bit in info

mike.geeves064
2021-08-30 11:35
Nod

pact544
2021-08-30 11:36
I think it's probably either using `{:?}` or just deriving Debug/Display and logging the object itself. You get a Rust-specific representation

mike.geeves064
2021-08-30 11:39
I've not actually implemented structured logs myself as such btw, but consuming AWS CloudWatch logs.. it'smuch nicer being able to filter and work with than just a stream of text, from my experience with them at least

mike.geeves064
2021-08-30 11:41
I suppose the flip side of "hiding away" that is a rust log is it could make it slightly more opaque for debugging rust problems, if the end user logs are formatted differently depending on which language they're wrapped in? Possible downside but I wouldn't consider it a huge one

tjones
2021-08-31 06:37
Last night I started on a PR to fix up the rust logs

tjones
2021-08-31 06:37
I don't know rust though

tjones
2021-08-31 06:37
so probably it's not correct


tjones
2021-08-31 06:40
> for debugging rust problems This is the purpose of the logging guidelines. If the log levels are used consistently across frameworks, we can pass the log level between frameworks and not be concerned about exposing the "wrong" thing. `TRACE` is what we'd want to use for "super detailed, you have to know the framework source"

uglyog
2021-08-31 06:53
I'll review that, but I'm going to warn you now that I work on the principle: info is for the user, debug is for me and trace for when you need to know what is going on in detail. I'm not going to trawl through trace level logging to try diagnose an issue a user is having.

tjones
2021-08-31 07:08
It's not actually ready for review yet (I'm not even sure it compiles)

tjones
2021-08-31 07:09
> I work on the principle: info is for the user, debug is for me This is why I asked about the guidelines before publishing them :confused: I think it's very useful to have a distinction between user's debugging of their own tests and maintainers debugging the framework.


uglyog
2021-08-31 07:13
I'm happy to accept some logging changes, but there are some debug level statements that are essential to stay at that level

mike.geeves064
2021-08-31 08:05
I would add, I think you could hopefully address both sides with a structured log approach :thinking_face: Filtering the "kind" for example

andrew.jensen
2021-08-31 16:57
has joined #libpact_ffi-users

tjones
2021-09-01 00:36
@uglyog I think your need to have a debug mode that isn't `trace` is a good one, but I'm not sure how to support it while also having a good debug mode for users. What about having an extra environment variable (eg `PACT_FRAMEWORK_DEBUG` that enabled extra debug logging?

tjones
2021-09-01 00:36
One problem in rust is that it seems to pick up the loggers from dependencies too - the final pass in the logging PR would have to be to match those to the guidelines as well.

tjones
2021-09-01 00:37
I really would like a common set of guidelines for all frameworks, so if the proposed guideline doesn't work for you, let's find one that does.

uglyog
2021-09-01 00:39
Rust logging doesn't let you filter dependencies (like you can on JVM). I'm sure eventually there will be support for it, but for now we get all the async and HTTP framework logs as well.

tjones
2021-09-01 00:48
hm ok

tjones
2021-09-01 00:48
maybe we need a different way to control the logging for rust

tjones
2021-09-01 00:48
`PACT_LOG_LEVEL` or something

tjones
2021-09-01 00:50
@matt.fellows did you say you hit a way to filter the logs in rust? I thought you did, but I can't find it in a search

matt.fellows
2021-09-01 00:52
:thumbsdown:

mike.geeves064
2021-09-01 00:54
I'm going to say structured logs again :smile: but I have no idea complexity involved to set that up in rust / the impact it could have elsewhere :thinking_face: (happy to look when there's next some time for a tangent but skill level might not be quite there) If you could add in tags against the types of errors you were interested in then worst case it's pretty straightforward to filter out those that don't have it when you're consuming

matt.fellows
2021-09-01 00:55
Structured logs could probably mean you can then filter out unknown packages i.e. dependencies if needed, which would be a crude way to achieve the above

mike.geeves064
2021-09-01 01:11
yeah that's what I'm thinking, https://substrate.dev/rustdocs/latest/slog/struct.Filter.html as far as I understand this, if you have your "normal" rust drain [outputting say to stdout/stderr], you can then take that drain and wrap it with a filter on each record to then e.g. output to your ffi log buffer?

tjones
2021-09-01 03:17
@mike.geeves064 possibly! Although, in pact-js, we don't want an FFI log buffer. pact-js wants Rust to log to stdout. So, I think the requirements are: ? Able to be rolled into a buffer for .net (and presumably others) ? Able to be logged to stdout for js (and presumably others) ? Not to have users needing to wade through logs that concern the implementation when debugging tests ? Not to have Ron / maintainers needing to wade through other package's trace logs when debugging pact. Have I got that last point right, @uglyog?

tjones
2021-09-01 05:05
Awesome! @mike.geeves064: Would this be something you're interested to take a look at? I'll wade in if you're not interested, but don't want to step on your toes if you had an approach in mind and were excited about looking into it

mike.geeves064
2021-09-01 07:17
I am always interested at playing with new things and excited about looking into them, this is the cause of many of my problems :joy: Where does it fit with priorities and timelines? If you're also interested and excited and it's blocking right now then it's probably best to wade in, if it's more on the chore side but needs doing to meet the log consistency goal I can take a look when I've finished the first bit of adding in tests for the python CLI wrapper, at least to get an initial poc of what I was thinking to see if it looks like a sensible direction or not

tjones
2021-09-01 13:35
I?m not keen to release pact-js backed by rust without sorting out the logging, but it?s not urgent- we have plenty to get on with and the only thing this blocks is the release

pact544
2021-09-01 13:37
Yeah likewise. Without really good logging support I'm not keen on releasing PactNet either. If tests fail then you need really good info on why

pact-slack
2021-09-01 15:03
has joined #libpact_ffi-users

kumasaka.tk
2021-09-03 17:48
has joined #libpact_ffi-users

mike.geeves064
2021-09-08 22:38
Getting closer to looking at logging, still a while off so let me know if it's needed too urgently to wait any longer :slightly_smiling_face: I've finished the next steps on the python side, trying to use the generic verifier arg functionality. It's working ok along with a couple of tests for the CLI pact-verifier and first steps of the method via code. Could do with some input on approach before taking it much further though. Currently it's fairly light on tests as I've offloaded all the logic of what args are needed onto the requirements of the FFI call to avoid duplication, which seems to work well. Need to see what else would actually be of value to include. What I've been wrangling with today is what to then do that works nicely on the code (i.e. not CLI) side. There are a few options I've been experimenting with, attempting to generate classes via different methods based on the FFI call, I've tried: ? via a library "python_jsonschema_objects" which makes the class from some JSON ? using the dataclasses "make_dataclass" ? [now removed] attempting to use pickle/dill/cloudpickle to save a generated class via those two and other approaches, hoping to then be able to generate and load "later" ? finally making some source code For comparison, very incomplete but functional alternatives are in here: https://github.com/mikegeeves/pact-python/pull/1/files#diff-323d43ee17cc3973c5557456838b3406710ad8f9d395fc3117acbe24b5ec9058 with the source code generated by that option currently here: https://github.com/mikegeeves/pact-python/pull/1/files#diff-cc76c1ff6a766e7d39a30eb0af4b35ec4d003594940b09bc295668426724a749 Generating some python source code (literally just containing the class) seems kind of clunky, but has been the only realistic way I've been able to then have something that will give type hints to users of the contents, since the other approaches are all generated at run time (I was hoping a serialised pickle would work round this, but seems not as it's still loaded at run time only). The idea being when downloading and packaging up the latest lib binaries, it could just generate then, meaning the maintainer would see if anything significantly changed as well. @tjones interested to hear your thoughts on that as an approach, we briefly discussed when first looking at it @elliottmurray could still do with some general input on if the approach/structure looks ok so far or any significant areas to change: https://github.com/mikegeeves/pact-python/pull/1/files assuming not I'll clean up what's in there, subject to opinions on code generating code which is then packaged up etc

mike.geeves064
2021-09-09 13:40
Starting to try and read up on the logging a little: ? as a first step I'm looking to swap out the println calls for logging, which I'm assuming should all end up as INFO (message to the user about their pacts) ? still output to stdout ? as well as ideally a stream and temporary file ? any of those print->info entries should be distinguishable from anything else that would try to log as INFO Is that in line with needs/expectations or anything misunderstood etc? First glance I can't see a stream to buffer with slog

tjones
2021-09-10 01:07
Do you mean in python or in the ffi?

tjones
2021-09-10 01:07
If you're asking about the python logging, this is probably not the right channel

tjones
2021-09-10 01:10
I'm not 100% sure I'm following here - let me see if I've understood: ? You're looking at generating types from the ffi ? This means that you could see at compile time if the interface of the ffi has broken (at least in terms of call signatures) is that right?

mike.geeves064
2021-09-10 06:16
FFI

mike.geeves064
2021-09-10 06:18
Yes that's largely it. Can do dynamically at run time but then you lose IDE hints for users which would be a rubbish experience

mike.geeves064
2021-09-10 06:22
In theory if it's say a new flag added, the maintainer wouldn't need to do anything else at all, just commit, if something is different, "politely discuss" with the Rust maintainer why backwards compatibility has been broken

mike.geeves064
2021-09-10 06:25
What functionality if looking at swapping print for logging of some sorts would be desired across the language bases

tjones
2021-09-10 08:44
In the FFI logs are already going to the logger

tjones
2021-09-10 08:44
do you mean the test output?

tjones
2021-09-10 08:44
I don't think the test output should go through a logger

tjones
2021-09-10 08:46
You can see the logs that are already logged in here: https://github.com/pact-foundation/pact-reference/tree/fix/cleanup-log

tjones
2021-09-10 08:47
I think test output is a different beast, because if it goes through a logger it would be harder to parse it. For test output, I think some kind of structured response is probably best (the consumer tests already have this, I believe)

mike.geeves064
2021-09-10 08:47
:thinking_face:

mike.geeves064
2021-09-10 08:47
That was where the suggestion of structured logging comes in, because it's then simple to pull out the message part

mike.geeves064
2021-09-10 08:47
I may have misunderstood what you meant by: > `Info`: You probably want to know this every time you run pact, and if tests are failing here is an explanation

tjones
2021-09-10 08:48
> What functionality if looking at swapping print for logging of some sorts would be desired across the language bases There's a comment on that above somewhere, I'm only partly here so I can't link it right now

mike.geeves064
2021-09-10 08:48
So you're not thinking include that in the logs then?

tjones
2021-09-10 08:48
For test output, we don't just want the "messages"

tjones
2021-09-10 08:48
because it's like "given this state, and this request, this response was verified"

tjones
2021-09-10 08:48
the problem with the logs is that they're super verbose right now

mike.geeves064
2021-09-10 08:49
Might be worth more of a conversation when you / someone is more here :slightly_smiling_face: I think I've possibly got a completely different understanding currently

mike.geeves064
2021-09-10 08:49
nod

mike.geeves064
2021-09-10 08:49
timezones are hard :slightly_smiling_face:


tjones
2021-09-10 08:49
eg this

tjones
2021-09-10 08:50
This doesn't fit the logging guidelines we're moving towards, but the problem is that we can't control logging for Rust libs easily. We get their debugs too

tjones
2021-09-10 08:50
so probably we need our own logger

tjones
2021-09-10 08:50
so it's about changing the currently logged things

tjones
2021-09-10 08:51
there's already a logger, but the logger logs to stdout. .NET (I think?) doesn't want stdout logs. It wants to get the logs and do something with them

tjones
2021-09-10 08:52
(probably print them itself)

tjones
2021-09-10 08:52
so there, structured logs would work nicely

tjones
2021-09-10 08:52
but it's not changing the printlns, because there aren't any

mike.geeves064
2021-09-10 08:52
(I am thinking which is slow :slightly_smiling_face: )

tjones
2021-09-10 08:52
hopefully that makes some kind of sense. I'll write more clearly when I'm not disappearing

tjones
2021-09-10 08:52
I'll be back later and/or tomorrow

tjones
2021-09-10 08:53
hope you're well!

mike.geeves064
2021-09-10 08:53
sure

mike.geeves064
2021-09-10 08:53
would a quick video call work better than typing long notes?

mike.geeves064
2021-09-10 08:53
(whenever, not right now)


mike.geeves064
2021-09-10 08:53
thinking of how time consuming it can be trying to give detail in a message

mike.geeves064
2021-09-10 08:54
I think I'm possibly heading in a different direction on some things but I'm not sure they're necessarily different :slightly_smiling_face:

mike.geeves064
2021-09-10 08:55
when suits? or alternatively just ping when I'm online and you have time :slightly_smiling_face:

mike.geeves064
2021-09-10 09:00
I definitely have some wires crossed as I was thinking more around rolling into a single filterable source but still with stdout, possibly around confusing build tests with pact tests

mike.geeves064
2021-09-10 09:00
anyway, talk another time then! :slightly_smiling_face:

tjones
2021-09-10 09:05
> when suits? I'll get back to you on this. Others might be interested too, idk

mike.geeves064
2021-09-10 09:08
I'll probably pause for a bit then, no point going on a tangent if it's not of value

mike.geeves064
2021-09-10 09:10
:thinking_face: normally I'd go through on a miro board (for example) and just run through a bit of a flow of the different types of information, where they go and where people would like them to go / what they want to do with it

mike.geeves064
2021-09-10 12:40
I've made a quick board as a starting point: https://miro.com/app/board/o9J_lxta2uI=/ - I'd like to try and understand when person of type x is doing y they would like info from a to go to b and c to go to d etc

mike.geeves064
2021-09-10 12:41
"so that they can..."

mike.geeves064
2021-09-10 12:41
tbc :slightly_smiling_face:

pedroefajardo_pactio
2021-09-10 23:51
has joined #libpact_ffi-users

tjones
2021-09-14 13:33
Has anyone had trouble with `--disable-ssl-verification` not disabling ssl verification? I'm not sure if we're invoking it incorrectly here: https://github.com/pact-foundation/pact-js/issues/736#issuecomment-919147536

matt.fellows
2021-09-14 23:09
I?ll take a look today Tim

mike.geeves064
2021-09-15 08:19
Re the various issues Beth's created on 'Set "enable pending" to true by default', that's a good example of where I would see it being beneficial having that single source of info with the method I created on the Rust side (retrieving the args and their defaults etc), so all the updating work would then involve is use the new Rust FFI lib version. Could still do with some input if anyone else thinks it's remotely a good idea, since it would be probably a bad idea if just Python had that approach, nowhere else (and I still don't know if anyone likes that approach on the Python side either :thinking_face: )

matt.fellows
2021-09-15 08:26
I'm still to catch up on that work, but how would that solve it?

matt.fellows
2021-09-15 08:27
The clients still need to update the mapping right?

mike.geeves064
2021-09-15 08:27
reduction of effort required, it should then just be version bump to use the new lib, and it will then pull in the defaults from there

matt.fellows
2021-09-15 08:27
I see

matt.fellows
2021-09-15 08:28
It's more than just arg mapping but also defaults

mike.geeves064
2021-09-15 08:29
yeah, so for the python one, it pulls in the --long-name -l [short name], ENV to use if available, DEBUG|INFO etc for options and default e.g. http for scheme, and I'm using that to automatically "populate" the args to call by cli to then use them

mike.geeves064
2021-09-15 08:29
and more recently, looking at generating some argument class to then be able to have some form of type hinting

mike.geeves064
2021-09-15 08:30
hence it's very much a, i think this could be an interesting approach but i could totally understand dislike as an approach :slightly_smiling_face:

mike.geeves064
2021-09-15 08:32
generating a class with the values in for example, I'm of two minds about, because "print out" something to make code kind of seems horrible but it actually works well :smile:

matt.fellows
2021-09-15 08:34
(Just with kids rn but I'm digesting)

mike.geeves064
2021-09-15 08:37
:+1: np, focus on kids! I'm just heading off for a while anyway

elliottmurray
2021-09-15 09:17
Hey Mike - so I have run through the code at a very high level and was 'digesting' this mentally. I've also just not had the headspace this last month or so for Pact generally so apologies - wasn't ghosting you!

elliottmurray
2021-09-15 09:18
While I do really like some of the suggestions - creates some nice pass thru and would in theory make all sdk's more aligned it also makes me a bit nervous when you go down this 'auto-generate' route. That's where I'm at really and haven't moved beyond that yet (well still trying to understand FFI tbh!)

elliottmurray
2021-09-15 09:20
Previously with Ruby there would occasionally be an issue with having to update an api it was often pretty easy to add it to click and change the code. Not saying this is optimal just wasn't my biggest pain point. So it's a trade off with some 'magic' versus a little more maintenance I guess?

mike.geeves064
2021-09-15 09:45
:100: it's very much a preference of approach, I like the idea of making the codebase as a whole much more DRY (across multiple languages) and overall reducing the amount of choice you need, it is adding in some magic. I'm totally with you on a bit nervous about auto-generated (imo I think overall it's ok, but it's not my codebase so I'm happy to keep in line) :slightly_smiling_face: In a "real world" situation, I'd generally try and have a call with a group to go through pros and cons of adding magic to determine if it's desirable to continue, bin the whole idea, continue if some concerns can be sufficiently addressed, or come to an agreement on the level/scope to implement something and where the line is Not sure the best way here? :thinking_face: Fine with shelving if that's the preference, but then need some input on what to do instead No problem about time, headspace is always tricky :slightly_smiling_face:

tjones
2021-09-15 14:06
Part of the challenge of the auto-generation approach is that it's hard to come up with a good solution that produces idiomatic code in all the languages and frameworks (have a look at the mess of inconsistency that is autogenerated swagger clients + servers for an example). I really like the idea of adding instrumentation to allow consumers of the ffi to "inspect" it, but I think it will be useful in different ways. For example, in pact-js, the CLI args are defined here: https://github.com/pact-foundation/pact-js-core/blob/master/src/verifier/arguments.ts - I don't think there's a lot of value in autogenerating this code for JS (even if it were possible), because the calling code would have to be updated anyway - even if we exposed the autogenerated code right to the boundary of pact-js, we still have to update examples, documentation, etc. On the other hand, manually maintaining this code is not especially onerous. We do occasionally have problems where the wrong argument is used (or arguments are removed / changed), so I see the arg-exposing functions you added being most useful in tests in pact-js - I'd love to have this implemented, and I think it's a clear improvement.

tjones
2021-09-15 14:09
The other thing that could be autogenerated is this type, which needs to match the declared functions: https://github.com/pact-foundation/pact-js-core/blob/master/src/ffi/verifier.ts A risk is that this type is wrong and we don't pick it up during tests. If we autogenerated it, it would solve that problem. Perhaps this can be done automatically by parsing the .h file, or exported during the build of the ffi. That would be cool. But, on the other hand, maintaining this file is not a significant amount of work - and anything that breaks the definitions in here should technically be a breaking semver change in the ffi.

tjones
2021-09-15 14:12
My summary from a pact-js perspective is: ? I think autogenerating the types would let us reduce some risks and may make maintenance easier (of course, it may make it harder, especially if the autogenerator required maintenance) ? However, I don't think those risks are especially large, and the maintenance gain seems small, so I'm unlikely to work on it as a matter of priority ? If someone else wanted to work on it, I'd welcome it

mike.geeves064
2021-09-15 14:13
(I love how FastAPI with pydantic actually nicely gives you the possibility of having validation "defined" which goes into your Swagger instead of the car crash of half assed Java annotations I dealt with in the past, but that's an aside :smile: )

tjones
2021-09-15 14:13
It does bother me a bit that we're a contract testing framework, but don't have a clear way to test the contract between the the boundary of either the rust or the ruby core.

mike.geeves064
2021-09-15 14:13
:joy:

mike.geeves064
2021-09-15 14:14
I was thinking earlier actually, I'm sure it was in some Pact blog/tutorial I read about pitfalls and what you don't want to do is just duplicate the same thing in your Pact tests, there's no point in having identical tests of exactly the same thing in multiple places

tjones
2021-09-15 14:14
> I love how FastAPI with pydantic Right! So, this is what I meant by "a good solution that produces idiomatic approaches" - if we *have* some tooling for autogenerating, I don't think we can do a one size fits all

mike.geeves064
2021-09-15 14:15
appropriate tests in the appropriate place

mike.geeves064
2021-09-15 14:16
:thinking_face: I get your point, but I'm not sure it would be a "can't", it is essentially an interface so as long as the interface provides what is needed you can, but I do agree about maybe it doesn't add value

tjones
2021-09-15 14:18
My summary from a pact-maintainer perspective would be: ? I think this is interesting but low priority for pact-js, because of the tradeoff of small amount of value for us, but probably medium-to-large time investment ? I think it might be more valuable to other pact implementations, depending on their idioms and maintenance challenges ? If it is more valuable to other pact implementations, I'm not going to argue against it

mike.geeves064
2021-09-15 14:20
The tests area I think is interesting, because I would question the value around testing what does it do when you call it with arg x and y but not z, and having business logic in the JS/Python etc to deal with what combinations of arguments you need.. because this is covered on the Rust side, and if the Rust side can [and should, and should have tests] making sure it is called correctly, I'm not sure you add value on the calling implementation essentially doubling up on that, you're adding in a lot of duplicate code/functionality/tests [there's for sure a line somewhere, obviously you want to have some tests to make sure it works etc, but maybe you don't need to test so much]

tjones
2021-09-15 14:22
Yes, that's very true. In pact-js, we're moving away from heavy validation of the arguments before passing to the binary, because otherwise it requires updates on both sides when they change. However, this means that the "contract" is that the binary produces good error messages appropriately

mike.geeves064
2021-09-15 14:23
which goes onto our other conversation around logging/output :smile:

tjones
2021-09-15 14:23
I think the duplication of validation discussion is unrelated to the autogeneration of a calling interface, though

tjones
2021-09-15 14:23
> which goes onto our other conversation around logging/output Yes, exactly.

tjones
2021-09-15 14:25
bedtime here - but if I had something to autogenerate the types for the JS side of the FFI boundary I would absolutely use it. I think maintenance tooling can save time or attention - and in this case it would save about 60 minutes of setup time, and no additional attention

tjones
2021-09-15 14:26
(for a better elaboration on the attention idea - here's an excellent talk that was here in Melbourne a few years ago: https://www.youtube.com/watch?v=6_q3kQUNpLA )

mike.geeves064
2021-09-15 14:26
:+1: thanks for the input, I'm having a look through there to see what I've missed/not come to yet

mike.geeves064
2021-09-15 14:26
trying to figure out what else is there that would be problematic :thinking_face:

tjones
2021-09-15 14:27
Apologies, it looks like that talk is from Sydney, not Melbourne. Unacceptable. Anyway, the talk is the same one, and it's still great.

mike.geeves064
2021-09-15 14:27
and some of the why :thinking_face: [for example deprecated could be useful to try and figure out how to put that in]

mike.geeves064
2021-09-15 14:27
:joy:

mike.geeves064
2021-09-15 14:28
I'll have a watch now

mike.geeves064
2021-09-15 14:30
I don't think that verifier.js would be that hard to generate programatically [although I don't do JS, but then I don't do Rust either :smile: ] The value thing is really hard, I think the pets vs cattle analogy might work here also, I liked moving away from even low maintenance servers that were manually rebuilt, to just something you can wipe and reproduce with confidence :thinking_face:

tjones
2021-09-15 14:30
I wrote pact-js's custom arg mapper (linked above) precisely to allow arbitrary handling of arguments - we have convenience mappers for common cases (including "just print a warning if someone uses this"), but can also provide arbitrary functions, because sometimes we will want to do something really user friendly that is easy to express in a few lines of code

mike.geeves064
2021-09-15 14:31
nod

tjones
2021-09-15 14:31
> I don't think that verifier.js would be that hard to generate programatically It absolutely would be easy to generate. But, it would lose the ability to be very human if we did that.

mike.geeves064
2021-09-15 14:32
I need to look more at the things using it aside from the CLI directly

mike.geeves064
2021-09-15 14:32
for python as well that is it works great for CLI just passing through args, but the generated objects and what to do with them is a lot more complicated

tjones
2021-09-15 14:32
It's not hard to generate, but it's also not hard to manually maintain

mike.geeves064
2021-09-15 14:33
for sure

mike.geeves064
2021-09-15 14:34
I'm still on the fence about the whole idea in a way, because even if the CLI part is way improved... if you still have to do basically the same thing to call it via a method anyway, I'm not completely sure it's better overall because it's following two different approaches -> also trying to figure out what else is missing to see if it could work for both

tjones
2021-09-15 14:35
In pact-js, I'm keen to find things that make things simpler for us. For example - @matt.fellows and I just lost two days of pact maintenance effort to: ? `npm link` doesn't always do the right thing with npm dependencies, and we use it to trial the existing examples against the current build ? For some reason, the musl version of the neon rust bindings for js doesn't build on node 16 (deep into mountain yak territory)

mike.geeves064
2021-09-15 14:35
ouch

mike.geeves064
2021-09-15 14:35
yeah I saw the abandon node 16 for now

tjones
2021-09-15 14:35
neither of those things are specifically to do with things that provide value to pact users (other than "pact currently uses them to test / build")

tjones
2021-09-15 14:37
So, as a maintainer, I'm mostly for anything that makes it easier to get value into user's hands. My recent experience is that more complexity is generally not the answer.

mike.geeves064
2021-09-15 14:38
agreed on that one

tjones
2021-09-15 14:38
neon was great for allowing us to easily spike a rust-backed pact-js and get it out into user's hands. But it made the build significantly more complex (and necessitated including rust directly in pact-js), which has in the longer term meant it's harder to get value out the door

tjones
2021-09-15 14:38
The moment in that talk that talks about attention is around the 22 minute mark

mike.geeves064
2021-09-15 14:39
```Simple is better than complex. Complex is better than complicated.``` :slightly_smiling_face:

tjones
2021-09-15 14:39
her point is something like "saving time is one thing, but this thing that doesn't save me time does save me attention, and that is better" (wildly paraphrasing from memory)

mike.geeves064
2021-09-15 14:40
yeah that makes sense

tjones
2021-09-15 14:40
Aaanyway, I really should get to bed. I'm supposed to be awake again in 6 hours

tjones
2021-09-15 14:40
good chat!

mike.geeves064
2021-09-15 14:40
I like automation, but not if it's obscure as a result

tjones
2021-09-15 14:40
Right!

tjones
2021-09-15 14:41
I'd like to automate the things that are regularly costing us time or attention. The typings to the ffi mostly cost us setup time and attention

mike.geeves064
2021-09-15 14:42
so if everyone thinks too obscure, bad idea :slightly_smiling_face: no objection there I would think hopefully, if you can make it generate things itself that as you mentioned wouldn't probably take a hugely shorter time to make a branch, update a version number and run a script to generate than it would to go through release notes and pull out variables, but the attention definitely does apply there

tjones
2021-09-15 14:42
An example of a significant win there is when @bethskurrie automated the version bump of the ruby standalone so that pact-js gets a PR every time a new release is made. It is SO GOOD

mike.geeves064
2021-09-15 14:43
nod

mike.geeves064
2021-09-15 14:43
I'm going to stop replying for now so you go to sleep :joy:

tjones
2021-09-15 14:43
Fair :joy:

mike.geeves064
2021-09-15 14:44
[one last one: there is still the balance with some, of if it is making new dtos etc you would possibly want to at least "code review" the changes before building and shipping, maybe]

mike.geeves064
2021-09-15 14:44
anyway, night :slightly_smiling_face:

tjones
2021-09-15 14:44
Also, I like that your message describing the auto version bump pretty much crossed with mine describing the same thing

tjones
2021-09-15 14:45
with pact-js, we chose to review manually rather than automatically merge and release

tjones
2021-09-15 14:46
which means the code review is a bit there

tjones
2021-09-15 14:46
It would be excellent to get the same thing happening with the FFI

tjones
2021-09-15 14:46
currently that's entirely manual

tjones
2021-09-15 14:46
anyway, yes. Goodnight!

mike.geeves064
2021-09-15 14:48
:joy: :wave:

mike.geeves064
2021-09-15 21:43
:thinking_face: I like to hunt yaks but I think I may accidentally farm a few thousand :thinking_face:

matt.fellows
2021-09-15 23:44
Tim and I are professional yak shearers

matt.fellows
2021-09-15 23:44
(I suppose Sheep, given Australia)

mike.geeves064
2021-09-16 12:10
(I like that video a lot, it also makes me happy that a woman can now give a talk on a subject like that, starting with "omg tangents what am I even doing" and not get shot down as "that's just because you're a woman so you can't be a good developer" progress! also I would not have the confidence to stand up in front of people and give a talk in my socks :joy: much respect :smile:)

tjones
2021-09-16 14:21
I think I watch it about once every 6 months.

mike.geeves064
2021-09-17 09:33
[:thinking_face: still not completely sure where to go with this especially on the python side, but while my model builds, I had a "quick" look at the identifying available functions from the library: ? looks like a pain trying to introspect within rust to pull it out via macros etc ? looking at the lib itself, there are some packages e.g. ffi-generate using clang to pull out, or swig which can generate the stubs and objects for just about everything other than JS :joy: but it all looks quite complicated ? so finally trying your suggestion of using the header itself [I did start with that one, found cbindgen, started looking at adding it, found it was already there, then saw the output and went elsewhere for a while :smile:), the ones setup in the build already are quite large and would be a pain to parse, so had a look at reducing that, and I can get cbindgen to produce a much smaller .h file with just the functions all nicely on one line, so with a quick grep it ends up as: > $ cat include/pact_stripped.h |grep -v -e "^$" -e struct | grep '(' > const char *pactffi_version(void); > void pactffi_init(const char *log_env_var); > void pactffi_init_with_log_level(const char *level); > void pactffi_log_message(const char *source, const char *log_level, const char *message); > int pactffi_get_error_message(char *buffer, int length); > int pactffi_log_to_stdout(enum LevelFilter level_filter); > int pactffi_log_to_stderr(enum LevelFilter level_filter); > int pactffi_log_to_file(const char *file_name, enum LevelFilter level_filter); > int pactffi_log_to_buffer(enum LevelFilter level_filter); > void pactffi_logger_init(void); > int pactffi_logger_attach_sink(const char *sink_specifier, enum LevelFilter level_filter); > int pactffi_logger_apply(void); > const char *pactffi_fetch_log_buffer(const char *log_id); > void pactffi_string_delete(char *string); > int32_t pactffi_create_mock_server(const char *pact_str, const char *addr_str, bool tls); > char *pactffi_get_tls_ca_certificate(void); > bool pactffi_mock_server_matched(int32_t mock_server_port); > char *pactffi_mock_server_mismatches(int32_t mock_server_port); > bool pactffi_cleanup_mock_server(int32_t mock_server_port); > int32_t pactffi_write_pact_file(int32_t mock_server_port, const char *directory, bool overwrite); > const char *pactffi_mock_server_logs(int32_t mock_server_port); > bool pactffi_check_regex(const char *regex, const char *example); > void pactffi_free_string(char *s); > int32_t pactffi_verify(const char *args); > const char *pactffi_verifier_cli_args(void); that I think that would be pretty straightforward to read in on the JS/python etc side and token match to produce the info for those types, it might even go in as-is with how the python one works .... you meant that, right? :slightly_smiling_face: ]

mike.geeves064
2021-09-17 10:37
> even if we exposed the autogenerated code right to the boundary of pact-js, we still have to update examples, documentation, etc. On the other hand, manually maintaining this code is not especially onerous. With the CLI example, why would there be any difference between the CLI provided by python, or the one provided by JS, .net, and so on? Unless I've missed something, I can't see why you would have any behaviour differences at all, you're wrapping up the functionality exposed by the shared lib, so if you end up with say python cli being `pact-verifier --some-user` but for the JS cli it is `pact-verifier --someUser` that seems like a very confusing direction, and I don't think that happens anywhere?

mike.geeves064
2021-09-17 10:39
-> why is there documentation and examples to update for each language anyway? vs a single source of the latest set of examples applicable to that version of the underlying library

tjones
2021-09-17 10:39
> that I think that would be pretty straightforward to read in on the JS/python etc side and token match to produce the info for those types, it might even go in as-is with how the python one works My point is, yes we could do this ,but it would be a fair amount of engineering effort and moving parts (which means more maintenance effort in the future) to achieve something that is not currently difficult or onerous to do by hand, except for the first time.

mike.geeves064
2021-09-17 10:39
(had a brief discussion with Matt around docs on this)

tjones
2021-09-17 10:40
> -> why is there documentation and examples to update for each language anyway? We have no spec for the implementation features (eg, matchers that are composed of other matchers, developer productivity helpers etc). Having something like that would be amazing.

mike.geeves064
2021-09-17 10:41
there's a lot of e.g. Pact docs have info on matchers, then each language then goes onto explain in the readme some similar but slightly different explanation, it's making a lot of work for everyone :smile:

mike.geeves064
2021-09-17 10:41
:thinking_face: as in some languages can do matchers of matchers but others can't?

tjones
2021-09-17 10:42
Yes, a single source of documentation on "this is how it works" with eg tabs for "show me this in each language" would be AMAZING

mike.geeves064
2021-09-17 10:42
nod nod


mike.geeves064
2021-09-17 10:43
sorry yes, ofc there are differences in the implementation of an example, syntax between languages, but that's just "translation" of the same thing, rather than one having an example while the other doesn't

tjones
2021-09-17 10:43
Even ignoring the obvious benefits for users (and not needing to maintain multiple instances of the same documentation), the benefit of "oh! This feature isn't available in that implementation" would be super super great

tjones
2021-09-17 10:44
Largely the reason we don't have this is "no one has had the time yet"

mike.geeves064
2021-09-17 10:44
:smile:

tjones
2021-09-17 10:44
I would wholeheartedly support any effort to do it

mike.geeves064
2021-09-17 10:44
I'm up for docs, although a little wary of giving the impression I half start a dozen things and finish nothing :smile:

tjones
2021-09-17 10:45
That's not (currently) my impression

mike.geeves064
2021-09-17 10:46
that's good at least :smile:

tjones
2021-09-17 10:46
I think the auto-generate-types-from-ffi project feels like a valuable spike, with the outcome that "actually this will work, but maybe not be as useful as it first looked"

tjones
2021-09-17 10:47
which I think is a good contribution, that you could consider finished without feeling too guilty (unless you want to keep going because you think it might yield more value, idk)

mike.geeves064
2021-09-17 10:47
back to those examples, so with CLI specifically, that is identical for each language wrapped up isn't it? I get the programatic verifier etc is going to have different examples :thinking_face:

tjones
2021-09-17 10:48
Yes, although where you might put it differs between languages. For example, it's valid inside an npm script, because pact-js exposes it to npm.

tjones
2021-09-17 10:48
you don't need a custom script to use the CLI in pact-js

mike.geeves064
2021-09-17 10:49
(I may be lacking a bit of domain knowledge here across the various languages which probably doesn't help)

mike.geeves064
2021-09-17 10:50
on the python side you have the pact-verifier "binary" you call from a shell as one part, but then also the python function for verifying you're calling in the code I'm firstly talking about that binary, where the python code is literally taking the args you give it on the shell and then calling the ffi library with it Secondly is the programatic .verify method(s), which is where the type generation comes in and gets more complicated

tjones
2021-09-17 10:51
> (I may be lacking a bit of domain knowledge here across the various languages which probably doesn't help) This is the IDEAL time to write docs. Because you'd be learning the concepts

mike.geeves064
2021-09-17 10:51
I'm torn between asking is that not the same on the pact-js side / telling myself to RTFM :smile:

mike.geeves064
2021-09-17 10:56
In terms of dropping or continuing, on the python side with the pact-verifier, I think that's simple and clean enough that I'm not sure why you (as in "one" rather than anyone specific!) wouldn't want to have the one less place to even have to think about For the other part around types I think there could be value but I'd happily just drop, I think it might be "too late" for this time unless there's more of a "yes that looks useful" since as you say, it's largely already done the first time anyway I've had fun finding out about Rust and FFI regardless so it's all good :slightly_smiling_face:

tjones
2021-09-17 11:06
> wouldn't want to have the one less place to even have to think about The challenge is that sometimes autogenerated implementations become more things to think about longer term. Of course, if it's valuable to you / pact-python, I'm definitely not suggesting stopping. I'm also planning to use the introspection you added to the rust side to do sanity checks in pact-js. So, thank you!

matt.fellows
2021-09-18 00:15
Man, everytime I say ?I?m going to respond to Mike? I come back and there is a novel in front of me :laughing:

matt.fellows
2021-09-18 00:15
so, I?ve read most of the conversation. I?m currently on the side of ?it could probably be improved, but also it?s not the biggest pain point?.

matt.fellows
2021-09-18 00:16
which doesn?t mean it shouldn?t be solved, but it?s probably a little further down the list. Manually mapping arguments hasn?t been a big problem and from a time-to-market perspective, the proposal probably won?t shift that all to significantly.

matt.fellows
2021-09-18 00:19
If I could hijack the conversation toward big problems that cost us the most time / effort: 1. Documentation (as Mike has mentioned and we have discussed in a few places) having an actual guide that takes everyone from first consumer test, to completed Nirvana with the language specific examples and uses the CLI for key moments would be a massive win. 2. Getting onto v3 / rust core (which also needs some better documentation/guides for developers) 3. Having a feature spec (cucumber or otherwise) that each language should be implementing to ensure consistency with implementation and usage (2) 4. Consistent documentation across projects. Ideally, everyone goes to http://docs.pact.io/<language url>, instead of various GH repositories. This also goes for Pactflow documentation

matt.fellows
2021-09-18 00:19
Documentation is probably the highest priority, because it?s what leads to the most questions/time spent on slack, away from building new features (e.g. [2])

matt.fellows
2021-09-18 00:20
Getting onto the Rust core is strategically important, because having different specification versions and inconsistent experiences acrosns languages is another big class of confusion/problems

matt.fellows
2021-09-18 00:20
The biggest blocker to (1) is just time and getting headspace to do it. A good spike to iterate on the format is probably the starting point

matt.fellows
2021-09-18 00:21
Biggest blocker to (2) is the provider verification logging, and better developer documentation, and of course, implementation

matt.fellows
2021-09-18 00:21
(3) is something @greg595au has been agitating a bit about, and would love to give him some support around it if we think it?s a good idea

greg595au
2021-09-18 00:22
has joined #libpact_ffi-users

matt.fellows
2021-09-18 00:23
(4) requires coordination across Pactlow and OSS folks, and some thinking about the commercial and other impacts of doing so. We all agree it?s a bit messy though, and could be improved (we have some good data/user research on the Pactflow side to back it up though)

mike.geeves064
2021-09-18 08:03
> Man, everytime I say ?I?m going to respond to Mike? I come back and there is a novel in front of me You've heard of "two wrongs don't make a \"right\"" :smile: (actually that wasn't as bad as it looked when I saw on Mobile :smile: )

mike.geeves064
2021-09-18 08:31
Tim and I had a call chat yesterday which was nice as well as helpful :slightly_smiling_face: Where I'm currently up to: ? I'm thinking I'll leave the Python pact-verifier largely as-is, using the Rust method to auto-magically provide the args and so on, since it Just Works already (needs tidying up a little and maybe a few more tests, but there's not really anything to "go wrong" there) ? For the more contentious verifier programatically, shelve that for now, I will leave in a generate script for reference/manual use and use the class it's created so far but not progress wiring up to run the generate script during package etc, that needs tidying up of where it's up to Logging: ? I think the stdout going via the logger [which can then just print straight to stdout if desired!] etc at least as an option could be beneficial, but now understand better the pain point around logging levels etc, so leave that for now ? Going to spike a little around what logger options there are to try and split out the rust/pact logs. It looked like some of the other loggers had a nice way to "if you already have logging this is how you can hook into/replace existing macros so you can use this logger instead with only 2 lines of code" for example, which might work to do something there. I came across some examples this morning that looked like it might be able to split out the logging levels based on crates which might be a really quick win but need to play around with it Docs: ? I like docs, more than happy to focus there ? (3) I like that idea, why not try and structure the docs around that even? Then you can have consistent docs across all languages with examples of everything you want to do? ? (4) I think that needs some thought on what that would mean exactly, unless you're going down a round like CDK for example where the various language docs are largely autogenerated, I would think you would want as little as possible documentation in a language specific doc, and as much as possible in a Pact doc which has the examples for the various language syntax (thinking of the matcher for example), there's no point having copy pasted docs for each language, it's just another place to update and then improvements to one language don't benefit the other vs single source of truth

mike.geeves064
2021-09-18 08:32
(4) definitely needs a lot of coordination to avoid upset over "why are you deleting all my docs for language x" -> "I'm not they're just over here now and I've added in all these other examples someone had done in language y"

tjones
2021-09-18 12:33
As a JS maintainer, I certainly would welcome "here's a PR that deletes your docs and replaces them with templates to fill in for the central docs"

mike.geeves064
2021-09-18 13:38
For sure, I just mean communicating what is happening so there aren't concerning surprises

pact544
2021-09-19 19:12
#libpact_ffi-users Can someone please check the performance of consumer tests in their library using the Rust FFI approach on Windows please? In PactNet we get really poor performance (each test taking ~2s) with the mock server, but this doesn't happen on Linux or when there's a proxy in the way (using Fiddler) on Windows either. It's all just plain standard .Net Code and the performance is really poor. There's some more detail about things I've done to try and work out why it happens here: https://github.com/pact-foundation/pact-net/issues/323 tl;dr it's only when you use the Pact mock server and only on Windows

pact544
2021-09-19 19:59
Oooooooooookay... So turns out if I replace `localhost` with `127.0.0.1` then the tests are super fast. Why on earth are they slow with `localhost` then?!

matt.fellows
2021-09-19 22:12
Hostname resolution?

uglyog
2021-09-19 23:06
Must be doing a DNS lookup, which is timing out.

matt.fellows
2021-09-19 23:29
I think it was first trying to bind to an ipv6 address

matt.fellows
2021-09-19 23:29
i.e. `localhost` was mapped to `::1` and then it falls back to other IPs

matt.fellows
2021-09-19 23:29
Should we support ipv6 in the mock server?

tjones
2021-09-20 08:11
Oh I know this one! Windows is suuuuper slow at resolving ipv6 / 4 fallbacks because it actually follows the standards. Everyone else ignored them.

mike.geeves064
2021-09-21 13:57
Hm, not entirely clear on the FFI libs required, just comparing between what was in the python FFI download, and the js's sh script, js has: 'nix: linux-x86_64.so.gz osx-x86_64.dylib.gz osx-aarch64-apple-darwin.dylib.gz win: windows-x86_64.dll.gz windows-x86_64.dll.lib.gz On the python side I've got: ```PACT_FFI_FILENAMES = [ "libpact_ffi-linux-x86_64.a.gz", "libpact_ffi-linux-x86_64.so.gz", "libpact_ffi-osx-aarch64-apple-darwin.a.gz", "libpact_ffi-osx-aarch64-apple-darwin.dylib.gz", "libpact_ffi-osx-x86_64.a.gz", "libpact_ffi-osx-x86_64.dylib.gz", "pact_ffi-windows-x86_64.dll.lib.gz", "pact_ffi-windows-x86_64.dll.gz", "pact_ffi-windows-x86_64.lib.gz", ]``` Does anyone know what/when the various additional files are required? :thinking_face:

tjones
2021-09-21 14:05
One of those is static and one is dynamic

tjones
2021-09-21 14:06
You don't need both from each pair, it just depends on how you link them I think

tjones
2021-09-21 14:06
This is what we use in pact-js:

tjones
2021-09-21 14:07
except we rename them so we know what version they were meant to be when they were downloaded

mike.geeves064
2021-09-21 14:07
:thinking_face:


tjones
2021-09-21 14:08
this downloads them

mike.geeves064
2021-09-21 14:08
yus, that's the one I was looking at for the list above :slightly_smiling_face:

mike.geeves064
2021-09-21 14:08
I do pay attention to your links sometimes :smile:

mike.geeves064
2021-09-21 14:08
[actually, slightly earlier one before a refactor I think, earlier in the chan anyway]

tjones
2021-09-21 14:09
Haha! Sorry, I was repeating myself from a PM so that others could see it too

tjones
2021-09-21 14:09
Also yes, this time I cleaned it up a bit before linking it :wink:

mike.geeves064
2021-09-21 14:10
yeah I meant the now broken link one, helpfully slack still had the contents, didn't know it did that

mike.geeves064
2021-09-21 14:11
> robust-bash.sh

mike.geeves064
2021-09-21 14:11
bit of an oxymoron there :smile:

tjones
2021-09-21 14:11
:stuck_out_tongue:

tjones
2021-09-21 14:12
shellcheck + that lib, and you'll be laughing. I have a blog post about it somewhere

tjones
2021-09-21 14:12
It includes the recommendation "don't write more than 200 lines in bash".

tjones
2021-09-21 14:12
....whooops.

mike.geeves064
2021-09-21 14:13
:smile:

mike.geeves064
2021-09-21 14:32
ok so I should be able to lose the .a. ones then :+1:

pedroefajardo_pactio
2021-09-22 20:06
hello everyone, Can you tell me what other language implementations are shipping pre-compiled FFI libs as [package] artifacts?

matt.fellows
2021-09-22 20:33
JS and .NET at the moment

matt.fellows
2021-09-22 20:34
Oh and the dart package

matt.fellows
2021-09-22 20:34
Python is WIP

matt.fellows
2021-09-22 20:34
Go can't package anything other than source code, but it uses the FFI

pedroefajardo_pactio
2021-09-22 20:34
wow, nice. thank you for the response.

tjones
2021-09-23 02:35
Why do you ask?

matt.fellows
2021-09-23 03:18
For context Tim, Perdo is looking at the Elixr implementation

matt.fellows
2021-09-23 03:19
the previous work done by @pact-slack integrated rust code directly (similar to Pact JS) and now that work is recommencing there, I?ve been recommending moving away from that approach.

matt.fellows
2021-09-23 03:19
It?s made even more difficult for Elixr users, because they?d actually have to have Rust/Cargo etc. installed on end-users machines (i.e. it?s not just a pain for maintainers, but also users)

tjones
2021-09-23 03:41
Right! Cool

pedroefajardo_pactio
2021-09-23 14:32
ya, i can understand that.

pedroefajardo_pactio
2021-09-24 02:19
What?s the strategy with raw FFI? We, @andrew.jensen and I, can think of two options: 1. Set up a CI pipeline for `pact_elixir`, so that every time we publish a new version of the library, we compile the Rust code for Windows, MacOS, and Linux, then include those compiled binaries in the packageExpect the developer to install the Rust toolchain on their computer, and have them compile the Rust code, even though they are interacting with it as if it is C code 2. Expect the developer to install the Rust toolchain on their computer, and have them compile the Rust code, even though they are interacting with it as if it is C code Do you recommend either one of those approaches or yet a different one?

pedroefajardo_pactio
2021-09-24 02:19
.


matt.fellows
2021-09-24 03:35
No need to compile rust!

matt.fellows
2021-09-24 03:36
your strategy should be to download the OS-specific FFI bundles at build time, embedding them into your elixr package

matt.fellows
2021-09-24 03:36
when developers install the elixr package, your code knows where to find the relative paths of the FFI libraries

matt.fellows
2021-09-24 03:39
with the FFI interface, you don?t need to think about rust at all. The libraries expose a C interface that can be directly used by any language that can interface to C (I believe Elixr can based on my reading). You just need to pop the libraries into a known location (e.g. the equivalent of `./node_modules` or `~./pip` ) and then link to it

tjones
2021-09-24 07:30
Yes, definitely you shouldn't need to compile any rust. The binaries are already built for the architectures we support, you just need to link them using whatever C bindings Elixir has available

tjones
2021-09-24 07:31
From experience with the other pact frameworks, it's best if you can bundle the binaries directly in whatever package manager `pact_elixir` is stored in

pedroefajardo_pactio
2021-09-24 10:04
Thank you fellas

andrew.jensen
2021-09-24 15:56
> your strategy should be to _*download*_ the OS-specific FFI bundles at build time, embedding them into your elixr package (Emphasis mine :laughing:) Aha! We hadn?t though of that being an ?option 3? but that seems like it should work. I?m not sure on all the details of how to do it idiomatically in Elixir but we can start looking into it.

tjones
2021-09-24 22:17
> *at build time* ^ You can do this at the time you build the elixir package, not at the time the user builds

tjones
2021-09-24 22:18
In pact-js, we do this with bash - here's the script (it also downloads the standalone ruby binaries): https://github.com/pact-foundation/pact-js-core/blob/master/script/download-libs.sh

matt.fellows
2021-09-24 23:50
Exactly. You want to ship a package that doesn't require anything special on the part of the user. No extra dependencies, or user build time downloads where proxies etc can get in the way

pedroefajardo_pactio
2021-09-28 10:58
hello all, I am on a mac I cloned and build the `c` bindings/FFI project in https://github.com/pact-foundation/pact-reference when i run. I am getting a `dyld: Library not loaded: @rpath/libssh2.1.dylib` when I run the command ```src/consumer-verification basic src/libpact_ffi.dylib``` I copied `libpact_ffi.dylib` to the same directory where ?consumer-verification? is. I?ve tried installing libssh2 using Brew, i recreated the links to point to where the library lives and still seeing that error. I?ve tried other things like what?s in this article https://blog.krzyzanowskim.com/2018/12/05/rpath-what/ to no avail. Can someone point me to how to get around this? I am sorry, the setup appears to be trivial and it might be so but I can?t figure it out.

matt.fellows
2021-09-28 11:32
how are you linking to the dylib?

matt.fellows
2021-09-28 11:32
Are you using the c example in there, or are you writing your own FFI integration?

matt.fellows
2021-09-28 11:33
I?d honestly start by downloading the dylib directly from Github, and creating a standalone script that can load the dylib and execute a function. Perhaps the verifier, because it will spit output if you don?t pass the correct args which means it worked

matt.fellows
2021-09-28 11:34
That being said, dylib is a dynamically linked library - that seems to indicate it doesn?t know where libssh is

pedroefajardo_pactio
2021-09-28 12:14
i am using the c example in there. i also downloaded the library directly from GitHub. Tried building it myself and the one i downloaded. i think the error is due to yet another library `libssl` that somehow the system is not finding even though it is on my machine in `/usr/local/Cellar` that is being pointed to via a soft link from a file in `/usr/local/lib`

pedroefajardo_pactio
2021-09-28 12:15
i thought I would start by looking at the `c` example in there.

pedroefajardo_pactio
2021-09-28 12:16
i am following the directions in the `README.md` at ?c/consumer-verification/README.md?

matt.fellows
2021-09-28 12:19
ah, I?m out - it?s C :laughing:


matt.fellows
2021-09-28 12:20
I think you can just skip to ?Loading NIFs in Elixir?


matt.fellows
2021-09-28 12:21
and print it out

andrew.jensen
2021-09-29 16:57
@matt.fellows are you thinking we should have a little bit of C code in the Elixir project in order to wrap the FFI lib, so it becomes a NIF? In order to make a C library into a NIF, it needs to be compiled with `#include "erl_nif.h"` and NIF-related args on the available functions. (See ?Defining a NIF? in the doc you linked) I see some downsides to doing it this way: ? Complexity of the pact_elixir library?s pipeline: we need to download the FFI bundle at package-time _and_ compile a C NIF wrapper around it at compile-time ? Complexity of the library?s code: we need to write NIF-friendly C shims around every FFI function, then Elixir shims around the NIF shims ? App build-time performance: We have to do the work to compile the C NIF around the FFI bundle Maybe we plan on using the https://erlang.org/doc/tutorial/introduction.html to raw C libs instead, like ports or port drivers, instead? That way we just rely on the FFI bundle itself.

matt.fellows
2021-09-29 23:24
No you don't need to write C code, you can just link the library directly (hence skip the step about C)

andrew.jensen
2021-09-29 23:25
Therefore, we should not write a NIF wrapper, right? EDIT: to clarify, not sure I fully understand the implication in your message, so just wanted to double-check!

matt.fellows
2021-09-29 23:27
This is where I am out of my depth and may well be giving bad advice.

matt.fellows
2021-09-29 23:27
Most languages have a way to just link to a C library

matt.fellows
2021-09-29 23:27
I don't fully appreciate the complexities of the NIF tho

andrew.jensen
2021-09-29 23:28
OK cool. Yeah I think we should be looking for those simpler approaches as well. I haven?t had to write one so I?m a little out of my depth too!

matt.fellows
2021-09-29 23:29
Our libraries export a C Interface, so if you can make Elixr communicate with that you should be golden

tjones
2021-09-29 23:30
So, in pact-js, we use a native wrapper provided by tooling that is designed to link from node. This means that: 1) We download the lib + bundle it before the pact-js package is published for users 2) When users install, there's a compile step (abstracted from us and users) provided by the node linking tooling If that tooling doesn't exist in Elixir and there are hoops to jump through to call a C interface, you might have to do something custom

tjones
2021-09-29 23:30
hopefully that isn't necessary, or whatever it is can be done automatically easily

andrew.jensen
2021-09-29 23:31
From the limited context I have at this point - Erlang+Elixir NIFs are an abstraction on top of FFI that give you more safety. You know how there are new classes of errors that can occur in FFI that wouldn?t otherwise happen in higher-level languages (segfaults, some types of memory leaks, etc.) so NIFs add some extra checking on inputs and outputs that go across the FFI bridge, so if something crazy happens in the FFI code, it?s less likely to blow up the higher-level runtime. But you have to opt into NIFs. In other words, you can?t create a NIF by just linking Elixir straight to a C lib, you need that C lib to have NIF headers.

andrew.jensen
2021-09-29 23:32
@tjones could you post a link to the source of that wrapper? That actually sounds pretty analogous to NIFs!

tjones
2021-09-29 23:32
I... can, but we don't even touch it

andrew.jensen
2021-09-29 23:32
Oh, the wrapper code is _generated code_, that?s what you?re saying, right?

tjones
2021-09-29 23:32
from pact-js' perspective, we just tell that wrapper to link the ffi lib (and describe the interface that we want)

andrew.jensen
2021-09-29 23:33
OK awesome, I?m hoping we can find something similar in the Elixir ecosystem

tjones
2021-09-29 23:33
I'd be very surprised if there isn't

tjones
2021-09-29 23:34
a quick google suggests that we _could_ parse the .h file and write a NIF wrapper fairly easily

tjones
2021-09-29 23:34
sooo hopefully someone else has already done that

andrew.jensen
2021-09-29 23:35
Yeah I?d love to piggyback on a battle-tested implementation of that header parsing


tjones
2021-09-29 23:35
(but I don't think that's going to be useful to you)

matt.fellows
2021-09-29 23:36
Sorry I'm just getting jab #2... Will jump back in here later

andrew.jensen
2021-09-29 23:42
Thanks for the link. I like seeing all the declarations there, that?s a good way to see the shape of the functions we need to call. I?m trying to figure out what libs we might need that would behave similar to the `ref-napi` and `ref-struct-di` packages. I don?t fully grok what they?re doing yet but I can see they?re providing TS definitions and? emulations of C structs through JS buffers?

andrew.jensen
2021-09-29 23:44
Anyway, this gives us some great things to research. Thank you both for the help!

tjones
2021-09-29 23:45
They're providing the bindings of node types to C

tjones
2021-09-29 23:46
so, we don't have to do anything special with C strings

tjones
2021-09-29 23:46
(for example)

pedroefajardo_pactio
2021-09-30 10:20
thanks matt a Timothy for your answers, thank you Andrew for the questions. Now i have a better idea as to what approach to take.

pedroefajardo_pactio
2021-09-30 11:40
@matt.fellows you said > Our libraries export a C Interface, so if you can make Elixir communicate with that you should be golden Do you mean in the Pact Reference Project? If not that project then which project? on an unrelated note: I cloned the pact-reference libpact ffi project and got the javascript and the c projects to build. Just yesterday I got the `c` binary to run. I did this with the hope of familiarizing how these languages define and then use the .dylib Pact libraries. From what was said above I think I have ideas as to how to take our next steps.

matt.fellows
2021-09-30 11:43
By C interface, I don?t me C code, I mean something that can interop with C itself (usually shipped in the form of a dynamic or static library. We suggest using one of the dynamic libs: .so, .dylib, .dll)

matt.fellows
2021-09-30 11:44
But it sounds like you have a grasp on it! :clap:

matt.fellows
2021-09-30 13:23
@uglyog is this what I think it is https://github.com/pact-foundation/pact-reference/commit/42be9eb8? :eyes: Do we need to migrate to the newer provider verifier methods for this to work, or is the second log extraction function (`pactffi_verifier_logs_for_provider`) that just uses the name of the provider sufficient? https://github.com/pact-foundation/pact-reference/commit/42be9eb8#diff-0683cbee93e01f96b27383c0954421fc5be638947d54311f880ba9b84ba2cb61R652

matt.fellows
2021-09-30 13:23
cc: @tjones

pedroefajardo_pactio
2021-09-30 14:04
ok great. yeah, i think i got it. thank you

tjones
2021-09-30 23:46
A warning for everyone - if you call `pactffi_write_pact_file`, it writes the pact file even if the test run was unsuccessful.

tjones
2021-09-30 23:47
Thanks. I don't think we need this for pact-js - what we do need is to be able to have the log levels standardised with pact-js.

tjones
2021-09-30 23:48
but it's a problem because Rust's logs are very noisy. I think the solution probably lies in having two loggers - one for the pact framework, and then the library logger for maintainers


matt.fellows
2021-10-01 03:53
Yes, sorry I was confused about what you wanted the other day - have had too many of these chats with people recently

matt.fellows
2021-10-01 03:54
I can look at the default noise (i suppose that would be INFO level). Anything there that is more about debugging a problem will go back to debug level. I?ll start there and we can iterate

matt.fellows
2021-10-01 03:54
I?ll use the existing Ruby output as a guide also (there are many notices and I think they are important)

mike.geeves064
2021-10-02 08:20
Having a look at this, or rather attempting to but a bit stuck getting started :slightly_smiling_face:

mike.geeves064
2021-10-02 08:20
Right, trying to take a look at the logging, but I'm having some difficulty reproducing some of the issues, I'll reply in thread to myself here to avoid spamming with long copy/pastes :slightly_smiling_face: TLDR: can't get it to spew out noisy logs as expected

mike.geeves064
2021-10-02 08:21
So, I'm on this branch: >  mgeeves@bearly:~/dev/GitHub/pact-foundation/pact-js-core$ git branch > * feat/ffi-consumer >   master I've changed the logLevel to trace: > mgeeves@bearly:~/dev/GitHub/pact-foundation/pact-js-core$ grep logLevel test/verifier.integration.spec.ts >     logLevel: 'trace' as LogLevel, And added in using the DEFAULT_ARGS to all the tests (was only used on 2?) > mgeeves@bearly:~/dev/GitHub/pact-foundation/pact-js-core$ git diff | head -40 > diff --git a/test/verifier.integration.spec.ts b/test/verifier.integration.spec.ts > index 8f037b2..88a54e1 100644 > --- a/test/verifier.integration.spec.ts > +++ b/test/verifier.integration.spec.ts > @@ -18,7 +18,7 @@ describe('Verifier Integration Spec', () => { >    const pactBrokerBaseUrl = `http://localhost:${PORT}`; >    const monkeypatchFile: string = path.resolve(__dirname, 'monkeypatch.rb'); >    const DEFAULT_ARGS = { > -    logLevel: 'debug' as LogLevel, > +    logLevel: 'trace' as LogLevel, >      providerVersion: 'VERSION', >    }; > > @@ -52,6 +52,7 @@ describe('Verifier Integration Spec', () => { >        it('should return a successful promise', () => >          expect( >            verifierFactory({ > +              ...DEFAULT_ARGS, >              providerBaseUrl: providerBaseUrl, >              pactUrls: [ >                path.resolve(__dirname, 'integration/me-they-success.json'), > @@ -64,6 +65,7 @@ describe('Verifier Integration Spec', () => { >        it('should return a successful promise', () => >          expect( >            verifierFactory({ > +              ...DEFAULT_ARGS, But if I try and look at the levels coming out: > mgeeves@bearly:~/dev/GitHub/pact-foundation/pact-js-core$ npx mocha test/verifier.integration.spec.ts 2>&1 | grep -E "DEBUG|ERROR|INFO|TRACE|WARN" | awk {'print $2'} | sort | uniq -c >       1 07:54:03.009 >       1 07:54:03.035 >       1 07:54:03.036 >       2 07:54:03.038 >       2 07:54:03.045 >       1 07:54:03.046 >       1 07:54:03.047 >       3 07:54:03.048 >       2 07:54:03.049 >       2 07:54:03.051 >       2 07:54:03.053 >       2 07:54:03.056 >       1 07:54:03.060 >       1 07:54:03.061 >       1 07:54:03.064 >       1 07:54:03.065 >       2 07:54:03.066 >       2 07:54:03.068 >       2 07:54:03.069 >       1 07:54:03.070 >       1 07:54:03.071 >       1 07:54:03.072 >       4 ERROR >      90 INFO >      34 WARN Those timestamps are from a slightly different formatted entry: > mgeeves@bearly:~/dev/GitHub/pact-foundation/pact-js-core$ npx mocha test/verifier.integration.spec.ts 2>&1 | grep "+0000] INFO" | tail -2 > [2021-10-02 07:54:28.500 +0000] INFO (1689259 on bearly): pact-core@13.1.7: Verifying Pact Files > [2021-10-02 07:54:28.501 +0000] INFO (1689259 on bearly): pact-core@13.1.7: Verification successful [9:00 AM] I'm not getting anything producing excessive Rust logs :thinking_face:

mike.geeves064
2021-10-02 08:22
Logs like this one are the type Tim was talking about ideally being reduced since they are more verbose than you would probably want as INFO when looking as a pact user: > [2021-10-02T08:07:03Z INFO pact_verifier::provider_client] Received response: Response ( status: 200, headers: Some({"access-control-allow-origin": ["*"], "content-length": ["26"], "content-type": ["application/json; charset=utf-8"], "etag": ["W/\"1a-ztXXi0g2amFzJAkK4azzbA+THms\""], "date": ["Sat", "02 Oct 2021 08:07:03 GMT"], "connection": ["keep-alive"], "x-powered-by": ["Express"]}), body: Present(26 bytes, application/json;charset=utf-8) ) .... but I can't see even with it set to TRACE a huge amount of logs coming from the Rust libs

mike.geeves064
2021-10-02 08:23
I was expecting to get flooded with the low level lib logs, but don't seem to be getting any :thinking_face:

mike.geeves064
2021-10-02 08:24
I may have misunderstood the starting point with this, if for example the logs being sent back via ffi are specifically the pact ones, and the low level Rust logs are already excluded, in which case I'm starting in the wrong place :smile:

matt.fellows
2021-10-02 08:25
Just on mobile (of course) but they definitely don't look like trace logs to me You could probably just invoke the provider verifier outside of node JS directly and just point at a pre canned pact file and any http server (whether it implements the pact or not)

matt.fellows
2021-10-02 08:25
I.e. compile it locally or pull the latest binary down

mike.geeves064
2021-10-02 08:26
:thinking_face:

mike.geeves064
2021-10-02 08:28
When you say directly, the ffi still needs to be loaded in by something, JS, python etc

tjones
2021-10-02 08:37
The rust core also has a CLI you could use

matt.fellows
2021-10-02 08:44
Yeah, the CLI is what I'm talking about. It's exactly the same code that fires. The only difference is how the arguments get there

mike.geeves064
2021-10-02 09:00
:thinking_face: so I've built pact_cli

mike.geeves064
2021-10-02 09:01
I assume not this one though

mike.geeves064
2021-10-02 09:01
> mgeeves@bearly:~/dev/GitHub/pact-reference/rust$ ./target/debug/pact-file-verifier -d /home/mgeeves/dev/GitHub/pact-python/examples/pacts --loglevel trace > Verification result is OK > > 1) /home/mgeeves/dev/GitHub/pact-python/examples/pacts/pact-consumer-one-pact-provider-one.json: OK > > > There were 0 error(s) and 0 warning(s) in 1 file(s)

mike.geeves064
2021-10-02 09:05
:facepalm: ok pact-verifier-cli, I didn't scroll

mike.geeves064
2021-10-02 09:31
and for my reference later, so then: > $ ./target/debug/pact_verifier_cli -d /home/mgeeves/dev/GitHub/pact-python/examples/pacts --loglevel trace --port 35159 seems to be it

mike.geeves064
2021-10-02 09:49
js-core bugfix from Tim and I think we're almost ready to start :smile:

tjones
2021-10-02 14:15
Yes. Someone broke the logging in js-core. And by someone I mean me

pact544
2021-10-05 18:59
Quick question - the `include_wip_pacts_since` argument for the Pact Broker, is there any documentation on what form that can take? I've had a look and can't find any.


mike.geeves064
2021-10-05 19:37
> /// If the `include_wip_pacts_since` option is provided, it needs to be a date formatted in > /// ISO format (YYYY-MM-DD).

matt.fellows
2021-10-05 20:45
I think it actually can take any date like thing, but ISO format is definitely supported


uglyog
2021-10-05 22:25
Examples are all ISO format

mike.geeves064
2021-10-06 06:01
Sounds like a bug if it can accept anything other than ISO :grinning:

matt.fellows
2021-10-06 06:22
I seem to recall that Beth said the gem it used could expect things like ?Wednesday 3rd March 2020?

matt.fellows
2021-10-06 06:22
but I may be remembering wrong

pact544
2021-10-07 08:19
Yeah, weirdly in my test for this feature it uses `5d` (as in '5 days ago') to pass in. If it has to be a date then I can change the API to make sure we pass in a proper Date object since currently it's just a string

mike.geeves064
2021-10-07 08:20
:open_mouth:

mike.geeves064
2021-10-07 08:23
From an API/testing pov that sounds like something likely to get unexpected/difficult to reproduce etc behaviour :thinking_face: Is that something with an actual use case people want? (Interested to understand rather than "that's horrible how could you!" :grinning: )

pact544
2021-10-07 08:23
Yeah I have no idea where I even got that from :joy: I'll fix it

mike.geeves064
2021-10-07 08:24
:joy:

matt.fellows
2021-10-07 08:33
I think this confirms my suspicion about it dealing with "date like" formats

pact544
2021-10-07 09:05
OK I've made that a proper date in PactNet now: https://github.com/pact-foundation/pact-net/pull/333

pact544
2021-10-07 09:57
Has anyone upgraded to FFI v0.0.3 yet? As soon as I do the verifier starts panicking, but without any output in .Net I can't work out why... 0.0.2 and earlier is absolutely fine, and I'm literally just upgrading the library version with no other changes

pact544
2021-10-07 10:01
Oh dear, this looks bad... I thik it's related to the change to use native cert stores: ```$ RUST_BACKTRACE=full /d/Downloads/pact_verifier_cli.exe --provider-name "Event API" --hostname localhost --port 9222 -- filter-consumer "Event API Consumer" --file 'C:\git\pact-net\samples\EventApi\Consumer.Tests\pacts\Event API Consumer-Ev ent API.json' --state-change-url http://localhost:9222/provider-states Verifying a pact between Event API Consumer and Event API thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: InvalidData, error: Custom { kind: InvalidData, error: BadDER } }', C:\Users\runneradmin\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.11.4\src\async_impl\http://client.rs:297:65 stack backtrace: 0: 0x7ff66797537f - onig_get_regex_by_callout_args 1: 0x7ff66798c23a - onig_get_regex_by_callout_args 2: 0x7ff66796ec18 - onig_get_regex_by_callout_args 3: 0x7ff667977f66 - onig_get_regex_by_callout_args 4: 0x7ff667977a49 - onig_get_regex_by_callout_args 5: 0x7ff6679785c5 - onig_get_regex_by_callout_args 6: 0x7ff6679781b1 - onig_get_regex_by_callout_args 7: 0x7ff667975c9f - onig_get_regex_by_callout_args 8: 0x7ff667978109 - onig_get_regex_by_callout_args 9: 0x7ff6679e18a0 - onig_unicode_define_user_property 10: 0x7ff6679e19b3 - onig_unicode_define_user_property 11: 0x7ff66767e528 - onig_get_options 12: 0x7ff6672ef2f6 - <unknown> 13: 0x7ff667347880 - <unknown> 14: 0x7ff667323e3e - <unknown> 15: 0x7ff6672fc7e0 - <unknown> 16: 0x7ff66730cd28 - <unknown> 17: 0x7ff66731467c - <unknown> 18: 0x7ff6672d6b59 - <unknown> 19: 0x7ff6673235bf - <unknown> 20: 0x7ff6672f5472 - <unknown> 21: 0x7ff667350283 - <unknown> 22: 0x7ff66735996b - <unknown> 23: 0x7ff6673200aa - <unknown> 24: 0x7ff6673296a6 - <unknown> 25: 0x7ff667350cd6 - <unknown> 26: 0x7ff66730d97c - <unknown> 27: 0x7ff667978b26 - onig_get_regex_by_callout_args 28: 0x7ff6673297c7 - <unknown> 29: 0x7ff6679c64d0 - onig_unicode_define_user_property 30: 0x7ffdd0ab7034 - BaseThreadInitThunk 31: 0x7ffdd1802651 - RtlUserThreadStart```

pact544
2021-10-07 10:10
I've raised the above issue here: https://github.com/pact-foundation/pact-reference/issues/156. It's definitely something to do with cert stores as the error comes from `reqwest` and relates to DER certs.

pact544
2021-10-07 10:41
If anyone has integration tests checking the pact file is written properly, also note that FFI outputs slightly different content on Windows and Linux: https://github.com/pact-foundation/pact-reference/issues/157


tjones
2021-10-07 11:26
(note that the build fails because we're having trouble with the ffi wrapper on node 16, but I think that's unrelated. I tried upgrading to 0.0.3 on the off-chance it would fix it)

tjones
2021-10-07 11:27
(also, it doesn't mean it works - those tests are not especially intensive)

mike.geeves064
2021-10-07 11:31
:open_mouth:

tjones
2021-10-07 11:32
I mean, they do do real verification. But, I wouldn't say it's a full suite

matt.fellows
2021-10-07 11:51
Just tested the latest locally, and it works against a pactflow hosted account (good)

matt.fellows
2021-10-07 11:51
So I thought, i?ll just double check it?s not also susceptable to the Let?s Encyrpt issue

matt.fellows
2021-10-07 11:51
```11:50:26 [ERROR] Failed to load pact - Could not load pacts from the pact broker 'https://host.with.letsencrypt.cert.com' - IO Error - Failed to access pact broker path '/' - error sending request for url (https://host.with.letsencrypt.cert.com/): error trying to connect: invalid certificate: UnknownIssuer. URL: 'https://host.with.letsencrypt.cert.com' Failures:```

matt.fellows
2021-10-07 11:51
Shit!

matt.fellows
2021-10-07 11:53
but then realised that isn?t a new Let?s Encrypt endpoint and was a bumsteer from a poster on GH. My mac doesn?t trust it, so I stopped panicking?

matt.fellows
2021-10-07 11:55
Line 297 is https://docs.rs/reqwest/0.11.4/src/reqwest/async_impl/client.rs.html#297, which is exactly where you?d expect to see problems in rustls-tls-native-roots

matt.fellows
2021-10-07 12:02
From what I can see, you must have an invalid DER certificates in your system which is causing that issue. Looking at the https://docs.rs/reqwest/0.11.4/src/reqwest/async_impl/client.rs.html#1695-1696, it?s assuming that the native certs library doesn?t fail (hence the panic), but that just defers to this https://github.com/rustls/rustls-native-certs/blob/fb25baaf27c4e70793c1600c844d6a644d0813c0/src/rustls.rs#L31, which attempts to load each certificate into the trust store. but if ANY certificate is invalid, it instead bails out. That seems strange to me, but perhaps there is a good reason for that.

rholshausen
2021-11-19 23:52
has joined #libpact_ffi-users

mike.geeves064
2021-12-01 22:11
Ohh, that's novel, I left a reference for myself and actually found it again :joy:

tien.xuan.vo
2022-01-04 16:39
Is it true that if we use `pactffi_using_plugin` , then we have to use `pactffi_interaction_contents` , and we can't use other ffi functions like: ? `pactffi_message_with_contents` ? `pactffi_with_body` ?

uglyog
2022-01-04 22:20
Yes, but that is only for content from plugins

uglyog
2022-01-04 22:21
It should be integrated into the other methods at some point, I'm just not sure how it would work

tien.xuan.vo
2022-01-06 01:36
Pact plugin driver doesn't give me the reason why the plugin can not be started: > 2022-01-06T01:30:14Z ERROR pact_plugin_driver::child_process] Timeout waiting to get plugin startup info: timed out waiting on channel > [2022-01-06T01:30:15Z ERROR pact_ffi::plugins] Could not load plugin - Plugin process did not output the correct startup message in 60 seconds: timed out waiting on channel

tien.xuan.vo
2022-01-06 01:36
If I run the csv plugin manually, I got this error:

matt.fellows
2022-01-06 01:37
I saw this problem on my Mac a month or two ago, I think there was an issue Ron was working through

tien.xuan.vo
2022-01-06 01:37
```./pact/plugins/csv-0.0.0/pact-plugin-csv 08:30:45 ./pact/plugins/csv-0.0.0/pact-plugin-csv: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./pact/plugins/csv-0.0.0/pact-plugin-csv) ./pact/plugins/csv-0.0.0/pact-plugin-csv: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./pact/plugins/csv-0.0.0/pact-plugin-csv) ./pact/plugins/csv-0.0.0/pact-plugin-csv: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./pact/plugins/csv-0.0.0/pact-plugin-csv)```

uglyog
2022-01-06 01:40
Are you running it in Alpine Linux?

matt.fellows
2022-01-06 01:41
ahh

tien.xuan.vo
2022-01-06 01:42
No, I am running on Linux Mint 20.2 (Based on Ubuntu 20.04)


uglyog
2022-01-06 01:45
Can you confirm what version of glibc you have?

uglyog
2022-01-06 01:45
You will probably need to install 2.14, or build the plugin against the older version

tien.xuan.vo
2022-01-06 01:54
> ldd --version > ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31

tien.xuan.vo
2022-01-06 01:55
right behind 2.32

uglyog
2022-01-06 02:15
Probably easier just to build the plugin on your OS

tien.xuan.vo
2022-01-06 05:55
I built it myself and it work fine.

tien.xuan.vo
2022-01-06 05:55
I'm just not sure if it's user friendly

uglyog
2022-01-06 05:57
Yeah, we will probably need to support the LTS Linux versions, so will need to build it for different glibc versions

tien.xuan.vo
2022-01-06 05:57
How can we verify provider with pacts created by plugins?

uglyog
2022-01-06 05:57
But this one is just a prototype

uglyog
2022-01-06 05:58
The verifier will try load any plugin required. It will have been written to the pact file

uglyog
2022-01-06 05:59
The plugin will need to be installed where the verifier runs

tien.xuan.vo
2022-01-06 06:00
Are there any extra steps or I just run like normal? I asked because the provider verifier failed without any reason. ```Xdebug: [Step Debug] Could not connect to debugging client. Tried: 127.0.0.1:9003 (through xdebug.client_host/xdebug.client_port) :-( PHPUnit 9.4.2 by Sebastian Bergmann and contributors. Test 'Provider\PactVerifyTest::testPactVerifyConsumer' started Verifying a pact between test_consumer and test_provider Given a message Given You can hear happiness staggering on down the street an alligator named Mary exists generates a message which includes metadata "routing_key" with value "wind cries" (OK) "queue" with value "wind cries" (OK) has a matching body (OK) footprints dressed in red generates a message which includes metadata "routing_key" with value "And the clowns have all gone to bed" (OK) "queue" with value "And the clowns have all gone to bed" (OK) has a matching body (OK) Test 'Provider\PactVerifyTest::testPactVerifyConsumer' ended Time: 01:40.082, Memory: 20.00 MB There was 1 failure: 1) Provider\PactVerifyTest::testPactVerifyConsumer Failed asserting that false is true. /home/tien/Projects/pact-php/example/tests/Provider/PactVerifyTest.php:63```

tien.xuan.vo
2022-01-06 06:09
Maybe the reason is I didn't set the value for `PACT_PLUGIN_DIR` env in provider verify tests. I will test later today. But the output does not contains any clue make it hard to debug.

tien.xuan.vo
2022-01-06 14:57
That's exactly the issue. I added the env `PACT_PLUGIN_DIR` and it work fine now

tien.xuan.vo
2022-01-08 08:19
I'm testing protobuf plugin and here are some problems I got: ? I downloaded this https://github.com/pact-foundation/pact-plugins/releases/download/protobuf-plugin-0.0.0/pact-protobuf-plugin-0.0.0.zip and extract to `/custom/path/to/pact/plugins/protobuf-0.0.0` (configured by `PACT_PLUGIN_DIR`), but it does not work, then I realized that I need to move `bin` and `lib` directories inside `pact-protobuf-plugin-0.0.0` directory up to parent directory(to `protobuf-0.0.0`) ? The file `/custom/path/to/pact/plugins/protobuf-0.0.0/bin/pact-protobuf-plugin` need to be executable (it's not by default) Do I need to create tickets in github for them?

tien.xuan.vo
2022-01-08 08:25
Does Pact Protobuf Plugin support `oneof` feature? I'm getting these error messages: ? `Failed to call out to plugin - Request to configure interaction failed: Message ShapeMessage has no field implementation` ? `Failed to call out to plugin - Request to configure interaction failed: Message ShapeMessage has no field shape` Here is my proto file: ```syntax = "proto3"; package plugins; option php_generic_services = true; service Calculator { rpc calculate (ShapeMessage) returns (AreaResponse) {} } message ShapeMessage { oneof shape { Square square = 1; Rectangle rectangle = 2; Circle circle = 3; Triangle triangle = 4; Parallelogram parallelogram = 5; } } message Square { float edge_length = 1; } message Rectangle { float length = 1; float width = 2; } message Circle { float radius = 1; } message Triangle { float edge_a = 1; float edge_b = 2; float edge_c = 3; } message Parallelogram { float base_length = 1; float height = 2; } message AreaResponse { float value = 1; }```

uglyog
2022-01-09 00:33
There is not much we can do about that, those bundles are produced that way by the Gradle application plugin. I've ported the plugin to one that is written in Rust. https://github.com/pactflow/pact-protobuf-plugin


tien.xuan.vo
2022-01-09 00:36
I didn't know this repository exist. Let me try

uglyog
2022-01-09 00:40
You will have to build it yourself, as you will also have the glibc issue

uglyog
2022-01-09 00:40
But I'll update the CI build to create a LTS version as well

tien.xuan.vo
2022-01-09 00:42
I will. Thanks for your support. You can do it later. Enjoy your holidays.

tien.xuan.vo
2022-01-09 00:43
I figured out how to use it properly (at least what I think). So `oneof` is not a problem for now.

tien.xuan.vo
2022-01-09 03:41
Actually `pact-protobuf-plugin` work fine on my machine, I don't need to build

tien.xuan.vo
2022-01-09 05:24
Replaced protobuf plugin java version by rust version, I can see that the `body` and `matchingRules` of `request` section is removed. I think it's a bug.

uglyog
2022-01-09 22:05
Can you raise an issue for that

tien.xuan.vo
2022-01-10 14:23
I can't reproduce this different, so I can't report it. But because my test passed with java version, then now failed with rust version, so I think something wrong here, but I don't know why. I managed to print out `mismatches` : ```[{"method":"POST","mismatches":[{"actual":"","expected":"","mismatch":"Failed to compare the Protobuf messages - Did not find a field with number 2 in the descriptor, Message is Some(\"AreaResponse\"), Fields are {\"value\"}","path":"","type":"BodyMismatch"}],"path":"/calculate","type":"request-mismatch"}]```

tien.xuan.vo
2022-01-10 14:24
Can you tell me how to show/get plugin's log (or debug info) when running consumer or provider tests?

uglyog
2022-01-10 22:24
The logs are captured at the level that your test runs as, so you shouldn't have to do anything. Just set your logging to debug.

tien.xuan.vo
2022-01-11 00:31
you means `LOG_LEVEL=debug` ? I think it does not work for me `LOG_LEVEL=debug phpunit --debug -c example/phpunit.plugins.xml`

uglyog
2022-01-11 00:34
Oh, sorry, it is invoked via FFI. You need to set the log level via https://docs.rs/pact_ffi/0.1.5/pact_ffi/log/fn.pactffi_log_to_stdout.html

uglyog
2022-01-11 00:34
Ideally, it should be set to the log level set in php

tien.xuan.vo
2022-01-11 00:37
Let me try

tien.xuan.vo
2022-01-11 00:55
I tried ffi functions and it seem does not work for me ``` $this->ffi->pactffi_init('PACT_LOGLEVEL'); //$this->ffi->pactffi_logger_init(); //$this->ffi->pactffi_logger_apply(); //$this->ffi->pactffi_log_to_stdout($this->ffi->LevelFilter_Debug); //$this->ffi->pactffi_log_to_stderr($this->ffi->LevelFilter_Trace); $this->ffi->pactffi_log_to_file(__DIR__ . '/log.txt', $this->ffi->LevelFilter_Debug);```

tien.xuan.vo
2022-01-11 00:55
The file `log.txt` is empty for me

uglyog
2022-01-11 01:05
You need to call `pactffi_logger_apply` at the end

tien.xuan.vo
2022-01-11 01:13
It work now by combining `pactffi_log_to_stdout` and `pactffi_logger_apply` Then I realized `$this->ffi->pactffi_init('PACT_LOGLEVEL')` output same log, but with colors so it look better. All I need to do is using `PACT_LOGLEVEL=debug` , not `LOG_LEVEL=debug` Silly me.


uglyog
2022-01-11 22:27
Thank you!

kyle.florence
2022-01-12 06:00
@kyle.florence has left the channel

pact544
2022-01-24 08:33
Are there any other docs for the new verifier FFI handles approach? There aren't many docs on the functions themselves (the only arg docs are basically for when it's a number interpreted as a boolean). I'm struggling to work out how to actually use this

pact544
2022-01-24 09:09
Maybe I'm just grumpy this morning, but I'm finding the FFI approach really difficult to work with. I've upgraded to the latest FFI (0.1.6) in order to start moving to verifier handles, and now all the existing verifier tests fail with an error code which just says they panicked. I have nothing to go off there. I don't have an awful lot of time to work on it, so now most of that is gonna be taken up trying to debug what breaking change there is in the FFI. Do we publish a changelog or an upgrade guide or something to help guide maintainers through breaking changes to the FFI? It's very difficult to dip in and out as an open source volunteer otherwise, and just kinda makes me not want to do it.

pact544
2022-01-24 09:23
Well at least the CLI panics as well ```$ pact_verifier_cli \ > --provider-name \ > "Event API" \ > --hostname \ > localhost \ > --port \ > 9222 \ > --file \ > "C:\dev\http://github.com\pact-net\samples\EventApi\Consumer.Tests\pacts\Event API Consumer-Event API.json" \ > --state-change-url \ > http://localhost:9222/provider-states Verifying a pact between Event API Consumer and Event API thread 'main' panicked at 'Client::new(): reqwest::Error { kind: Builder, source: MissingOrMalformedExtensions }', C:\Users\runneradmin\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.11.7\src\async_impl\http://client.rs:1251:38 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace```

pact544
2022-01-24 09:24
Oh no, I think it's native TLS certs again...

tjones
2022-01-24 09:46
> It's very difficult to dip in and out as an open source volunteer otherwise, and just kinda makes me not want to do it. This was my experience too

tjones
2022-01-24 09:51
I think it's worth taking a step back and designing the interface to the shared core so that it has first-class support for the client frameworks. For example, at the moment it's hard to know what the lifecycle is intended to be for the different methods (eg, some methods can be called more than once, some silently clobber information - see https://github.com/pact-foundation/pact-reference/issues/172). A related issue is that if a password is passed via an environment variable as well as via the options, then the verifier fails with an error message that doesn't really describe the situation unless you know how it is implemented. At the moment, we have to implement this all client-side, which would mean re-implementation in every framework. I don't think this is the intention of the shared core, but without documentation I can't tell if it is the intention or not.

tjones
2022-01-24 09:51
I also can't tell what preconditions are meant to be met for each method.

tjones
2022-01-24 09:52
I'm leaving the project at the end of the month anyway, but my current feeling for pact-js is that it would be less trouble to have our own native JS core.

mike.geeves064
2022-01-24 10:18
:thinking_face: I really like the idea of shared etc, but I can see how that's really hard to do from an open source pov, imo you need to be able to have "group" discussions and have everyone on board with a direction etc, which seems very hard in an "async" way of working :thinking_face:

matt.fellows
2022-01-24 10:23
> A related issue is that if a password is passed via an environment variable as well as via the options, then the verifier fails with an error message that doesn?t really describe the situation unless you know how it is implemented. that is not an issue with the handle based interface that Adam is moving towards. The previous one was just a slimy interface on top of the CLI, but the new one is different altogether and doesn?t have this problem (and others).

matt.fellows
2022-01-24 10:24
> Oh no, I think it?s native TLS certs again... I need to refresh where that issue got to. I seemed to recall reqwest needed an update to the latest and/or there was a PR to reqwest that solved the problem. I?ll add to review this week

pact544
2022-01-24 10:25
The new FFI has some confusing points as well though (that don't lend to a fluent interface), and some args that I just can't work out. e.g. this will use basic auth over token auth if you provide both: ```fn pactffi_verifier_broker_source( handle: *mut handle::VerifierHandle, url: *const c_char, provider_name: *const c_char, username: *const c_char, password: *const c_char, token: *const c_char )```

pact544
2022-01-24 10:26
And I can't work out what the last param of this one does: ``` fn pactffi_verifier_set_filter_info( handle: *mut handle::VerifierHandle, filter_description: *const c_char, filter_state: *const c_char, filter_no_state: c_uchar )```

pact544
2022-01-24 10:27
Oh does that mean "only run interactions if they have no provider state"? But then what if you pass a `filter_state` as well?

matt.fellows
2022-01-24 10:28
> I?m leaving the project at the end of the month anyway, but my current feeling for pact-js is that it would be less trouble to have our own native JS core. Let?s try and be constructive here. The shared core is a very large beast and any attempt to rebuild it will run into issues of backwards compatibility, interface design, teething issues etc. Unless we can get the whole community to build together, and even then? It was largely built in personal time (similar to Adam?s comment) and that makes it even more difficult. We?re investing more into it now since Pactflow has been a thing, which has led to several important advancements. This being said, I think it would be wise to try and get our collective thoughts for improvement together. What do we think the best way of doing that is?

pact544
2022-01-24 10:28
To answer my own question - if you specify both then the filter wins and the final arg is ignored

matt.fellows
2022-01-24 10:29
Sadly Adam I?m not really across the handle based interface, but hopefully Ron can chip in with some guidance. I just know that it apparently solves the existing interface problem (what other issues it might produce I can?t yet say!)

matt.fellows
2022-01-24 10:30
I do know a few of the models changed (I tagged you in a thread a while back, which I know, is not ideal). We discovered a few of the structs were exposing their insides, and Ron converted them to Opaque types (essentially, a uint)

pact544
2022-01-24 10:33
I think one big hurdle to have this used in prod at a wide scale is that when it fails I just got an "it panicked" return code. To debug that I had to run my test in the debugger to start my API, set a breakpoint to stop the test actually running and then manually call the API with the verifier CLI (which is using a different version of the crates to the FFI afaict). That's quite an involved debugging process, especially for an issue which probably only happens on specific machines (because of the native cert store). We can't really ask users to do that when they have issues, but without that panic info we're pretty stuck with support.

matt.fellows
2022-01-24 10:36
Yeah, it looks like there are a couple of libraries that have OS/platform type switches in them

matt.fellows
2022-01-24 10:36
TLS native certs is one, and there is a magic mime detection one that has different behaviour depending on runtime shared libraries. As a principal, I think we want to avoid this

tjones
2022-01-24 10:36
> The previous one was just a slimy interface on top of the CLI, but the new one is different altogether and doesn?t have this problem (and others). I'm not complaining about that specifically, I'm saying the problem of error messages that might only make sense if you know how the implementation works seems to exist throughout the core.

tjones
2022-01-24 10:37
I think in general, it would benefit from sitting down and thinking about what the best experience for clients would be

tjones
2022-01-24 10:37
and what that boundary looks like

tjones
2022-01-24 10:39
For me, the approach I would like is to agree on some values that guide the design - like I proposed for the logging levels

matt.fellows
2022-01-24 10:40
I?m sure there are a bunch of principles, so articulating those might be a good start and then we can iterate from there

pact544
2022-01-24 10:41
It's weird because we've got like libraries depending on libraries, and I know the core is at the 0.x stage which says "breaking changes can happen". We really do need to keep those breaking changes to a minimum though, and write upgrade guides for maintainers if we do introduce them. Otherwise we've all got to go digging into the core every time we upgrade and it breaks, and as we've said it's a big beast

matt.fellows
2022-01-24 10:41
The feedback on the ?doesn?t lend to fluent interface? is interesting, because we?ve seen feedback that suggests it encourgase that (which in the context was a negative). The point here, is we ought to seek feedback from the community on what?s goig to work best, make a decision and move forward

matt.fellows
2022-01-24 10:42
> We really do need to keep those breaking changes to a minimum though, and write upgrade guides for maintainers if we do introduce them. Otherwise we?ve all got to go digging into the core every time we upgrade and it breaks, and as we?ve said it?s a big beast (edited) I think in the 0.y.z line there were some, but in the x.1.z line the position is no breaking changes. But yes, I agree

pact544
2022-01-24 10:43
The one I was specifically thinking about was this one: ``` fn pactffi_verifier_set_verification_options( handle: *mut handle::VerifierHandle, publish: c_uchar, provider_version: *const c_char, build_url: *const c_char, disable_ssl_verification: c_uchar, request_timeout: c_ulong, provider_tags: *const *const c_char, provider_tags_len: c_ushort )```

pact544
2022-01-24 10:43
That's just one big multi-purpose function, instead of more fine-grained ones which you'd typically get in a fluent interface

matt.fellows
2022-01-24 10:44
yep. If we add a new option, that method will break. (well, depends on the defaults, but probably not ideal)

mike.geeves064
2022-01-24 10:44
back to the async issue, responsive to "this is weird, having problems with this change" vs a more planned "we are going to look at doing this, does it make sense", and getting some feedback before changes maybe?

pact544
2022-01-24 10:44
Yeah that :+1: And the break will manifest as a segfault or something equally unhelpful at runtime, which isn't a great devex for maintainers

mike.geeves064
2022-01-24 10:47
:smile: it's kind of sad, the whole rust......you can't get null pointers, they all have to be handled, everything is safe, right up to the point where you have to say FFI, unsafe, oh well :smiling_face_with_tear:

matt.fellows
2022-01-24 10:48
How would we like to collaborate on this? I think we?re going to have to accept async, because physics, but we could probably get a few face-to-face sessions (e.g. using Miro / google docs) and get a plan down. And then we can use tools like GH projects to manage things.

tjones
2022-01-24 10:49
> The feedback on the ?doesn?t lend to fluent interface? is interesting, because we?ve seen feedback that suggests it encourages.... I would absolutely agree that I don't think it leads to a fluent interface, at least not from a pact-js perspective. Critically, the "test name" part is promoted to a first class concept, whereas the ruby binaries don't seem to care about the name.

tjones
2022-01-24 10:49
In pact-js, we'll have to write something into the DSL that catches the test names and warns the user about repeat names

pact544
2022-01-24 10:50
From my perspective, probably all I need right now is some more guidance about how the verifier handles work, unless we're planning to split those up into more fine-grained APIs soon. Even just docs on the functions would be fine for now (documenting what each arg does, which ones are exclusive, what happens if you specify 2 exclusive args, etc)

pact544
2022-01-24 10:52
I'll follow the fluent API pattern in C#, and then I'll just have to store some stuff in memory and pass it all off to the FFI at the end I think, e.g. for that big options func

pact544
2022-01-24 10:52
It'll be annoying if you do something weird though, because the error won't occur at the point where you expect it to

mike.geeves064
2022-01-24 10:55
[I still like the idea of magic code based on rust introspection generating the interface]

pact544
2022-01-24 10:57
I think you'd quickly end up with non-idiomatic code if you did that though. That's how Google do all their C# client libraries and they're _rubbish_

mike.geeves064
2022-01-24 11:05
I think it depends on how you wrap it up, it looked promising on the python side at least to end up being able to generate the fluent interface, just depends on what you can do with the magic bit in the middle. Non-issue now anyway, I gave up with trying to progress it for python I think a miro board of some sort and bit of a GH project approach would be helpful somewhere, even to just be able to get an idea of what languages need to do what, and try and make sure feedback can be covered across them, if some proposed approach would be for some reason problematic in something

mike.geeves064
2022-01-24 11:31
:thinking_face: re @pact544?s point on usage, would it help to have integration level reference implementation test examples, so the various languages could then perform those tests to get a better idea of overall compliance and behaviour?

pact544
2022-01-25 09:24
Sorry, I have loads of questions about the FFI that I'm just not getting. First one - What's the difference between these things? Can I use them all at the same time? Provider tags is similar from the broker snippet, is that filtering by provider tags or setting provider tags for verification results?

matt.fellows
2022-01-25 09:39
I think filters is a method that is analogous to the `--filter-consumer` CLI option. It looks to take an array of strings The `consumer_version_selectors` is the newer way of specifying which contracts should come from the broker. It looks to accept an array of strings, each string being the same JSON shape that the CLI takes. `consumer_version_tags` is the old way of specifying the pacts to select, which only uses tagcs. I believe they can all be used simultaneously, albeit you usually would not want to use tags if you are using the other method. @tien.xuan.vo looks like a lot of these handles were via PR #145. Are you able to shed some light on them?

matt.fellows
2022-01-25 09:41
Apologies, today got away from me.

pact544
2022-01-25 09:43
So is provider tags also a filter?

pact544
2022-01-25 09:44
In this one, is this the name of the provider or the consumer? And I'm assuming `scheme` is a typo there, because it's parsed to `version`. Again, is that the consumer or provider version?

matt.fellows
2022-01-25 09:46
oh, `provider_tags` are about describing the current provider that is verifying the pacts, and is used in pending pacts calculations

matt.fellows
2022-01-25 09:47
i.e. consumer version selectars are about finding consumers that match a certain tag/branch/environment etc. provider tags (and related option like `provider_branch` ) are about communicating details about the provider. The pending status is calculated based on the details of the provider doing the verification

pact544
2022-01-25 09:47
Oh, well then what does this do?

pact544
2022-01-25 09:47
You can see my confusion right? :smile:

pact544
2022-01-25 09:47
The terms all appear to be overloaded and it's often unclear which you should be using, and there's hardly any docs explainnig it

matt.fellows
2022-01-25 09:51
yes, it?s unclear to me too

pact544
2022-01-25 09:52
I'll try to soldier on with the bit I can do. The internal state that's being built up is already huge though and I've not started the broker options yet :open_mouth:

matt.fellows
2022-01-25 09:52
It _looks_ like the `..with_selectors` method was the original all in one method, and then other more granular methods came along via the PR mentioned above.

matt.fellows
2022-01-25 09:53
~yes, I believe it is a typo/copy-pasta and should be version. I?d say it?s the provider name based on context~

matt.fellows
2022-01-25 09:54
oh, no!

matt.fellows
2022-01-25 09:55
That should be populated with `pact-net` and the version of the Pact .NET library. It will be used to emit anonymous usage metrics to GA (see #)

tien.xuan.vo
2022-01-25 09:57
I'm working so I can't answer quickly. Yes, I created MR to add those missing ffi functions, but I'm same with you, still learning pact by create some simple merge requests, so I don't understand much. Here are something that I understand: ? `set_consumer_filters` filter pacts by consumer. I have an example here in PHP if you interested in https://github.com/pact-foundation/pact-reference/blob/master/php/src/provider.php#L41 ? `consumer_version_selectors` All I know it's a new way to filter pacts by consumer. There is a doc for it here https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/. I didn't use it yet. ? `consumer_version_tags` I don't know this, but Matt just said above it's just an old way to filter pacts ? `provider_tags` Also I don't know this one. This comment is from `Rust` code: `Tags to use when publishing results`

pact544
2022-01-25 09:58
Oh! OK that wasn't clear at all. Cheers for that

pact544
2022-01-25 09:58
We need to be able to disable those usage metrics as well then don't we? I don't see an option for that on the FFI

matt.fellows
2022-01-25 10:01
It can be disabled via an environment variable (it will actually print it out to users)

tien.xuan.vo
2022-01-25 10:02
I don't know this one. It's new to me too. And I think you are right about typo. I think you can create merge request to fix it

matt.fellows
2022-01-25 10:02
```pact_do_not_track=true```

matt.fellows
2022-01-25 10:03
This makes it consistent across other languages (we currently support that in pact-node to track downloads)

tien.xuan.vo
2022-01-25 10:03
I can confirm it's printed out. But I didn't try to disable it yet.

matt.fellows
2022-01-25 10:03
We really appreciate your enthusiasm and help so far Tien!

pact544
2022-01-25 10:15
Gotcha

pact544
2022-01-25 11:58
I just don't think this API makes sense. It forces you to specify the `provider_name` again, but you already had to supply that in the `set_provider_info` call (and in the PactNet code, you no longer have access to it because of the typestate pattern). It doesn't force you to set `provider_version` even though that's required for publishing results, and then `provider_version` is on a different func `set_verification_options` which you can call even if you aren't using a pact broker source, which would make no sense. If it's not intended to specify publishing options on this func, it's unclear why `provider_branch` and `provider_tags` are on there as those are publishing options. I'm having to try to tie my API code in knots to conform to that API whilst still making it usable and safe, which probably means other library maintainers will also. Is this the final API we're sticking with and we just need to get used to dealing with its quirks or are we planning on changing it to express its invariants properly?

pact544
2022-01-25 12:03
And then this func doesn't make sense either. Some of those are applicable even if you aren't publishing results (like SSL verification and request timeout), but others only make sense if you are publishing results, like provider version and tags

pact544
2022-01-25 12:04
In fact, the SSL and timeout options are applicable regardless of which source you're using, whereas the others only make sense if you're using a broker source

matt.fellows
2022-01-25 12:09
> Is this the final API we?re sticking with and we just need to get used to dealing with its quirks or are we planning on changing it to express its invariants properly? (edited) with this feedback, I can?t see us not wanting to change it, unless there is something I?m missing. Tien wrote it for Pact PHP, so may have some maintainer implementation advice

pact544
2022-01-25 12:23
The only way I can see it working is if you keep one huuuge state object and then try to build it up as you go, then try to do all the FFI calls at the end. That's very error prone though, e.g. you could set both a file source and a URL source. At first count I was up to 26 parameters on the state object doing it that way, which just felt totally wrong

pact544
2022-01-25 12:24
I've had to make a breaking change to PactNet to support this atm, and I can definitely see some more coming. e.g. request timeout and SSL verification could really do with being split from the publish options

pact544
2022-01-25 12:42
Arghghgh all that and the logs still don't work

mike.geeves064
2022-01-25 13:32
:worried: I did start trying to look at the logging, I wanted to get a bit of a baseline with some examples to compete between what happens currently Vs with ffi for the various languages, and what would be a good solution for all, e.g. logfiles Vs stderr, I think there are some differences between languages making that more complicated than one size fits all

mike.geeves064
2022-01-25 13:34
Do you have any good (shareable) examples to figure out what's there now/used to be there/would like to be there?

pact544
2022-01-25 13:47
I think I'm gonna try setting the log sink to write to file at the moment just to help me debug, but that's not really a good long-term solution because people do things like run tests in a Docker container with a read-only filesystem

pact544
2022-01-25 14:23
OK, so I do get logs via the buffer, but only at TRACE level. There are no logs at DEBUG or higher... And there are no verification errors or anything like that either :disappointed:

pact544
2022-01-25 14:27
Ah, all the calls inside the `pact_verifier` crate are just `println!` instead of `info!` or whatever, so they never end up going to the log buffer. They're just going to stdout, which is no good

pact544
2022-01-25 14:31
And lots of the messages have ANSI colour code stuff in them, so it's not an easy find and replace of `println!` with info/log/etc either :disappointed: Well, still no logs for PactNet then!

pact544
2022-01-25 15:06
When the Rust lib triggers the provider state endpoint, how come it's not providing a `Content-Length` or `Transfer-Encoding` header? .Net will reject all requests that don't do that, which is why my CI is currently failing

pact544
2022-01-25 15:11
Here's the relevant CI logs, but it's getting back a HTTP 411 Length Required https://github.com/pact-foundation/pact-net/runs/4938617118?check_suite_focus=true#step:8:814

pact544
2022-01-25 15:23
I've published a draft PR for moving to the new verifier handles approach here: https://github.com/pact-foundation/pact-net/pull/353 All the tests pass, but there's still a number of things that aren't supported, and some changes that I think need making to the FFI (unfortunately, breaking ones). I've documented some of them on the PR description.

pact544
2022-01-25 15:27
I think one absolutely huge thing we need is a simple way to get back the nice friendly messages about the interactions that are running, their status and the overall mismatches summary you get at the end. At the moment there are two big problems with it: 1. They only go to stdout, and include ANSI colour code chars and stuff 2. They interleave with all the other log messages, so it's really hard to actually follow them Ideally the output would start with a section summarising what happened and what errors there were, and then the detailed logs of what it did would follow instead of interleave with them. That would make the DevEx really nice for when things go wrong, but also provide sufficient information to debug if it's not immediately obvious why you have errors (although in my experience it's almost always obvious once you see the mismatches)

pact544
2022-01-25 15:30
i.e. I want what the CLI produces to come out first, and then the actual log messages (with the log level, file source etc) to come out separately instead of interleave

mike.geeves064
2022-01-25 17:58
I was looking at structured logging to see if that could be a way to work well with different clients, then you can have more control over different types of logs and filter in ways other than just the level, but didn't get very far

mike.geeves064
2022-01-25 17:59
The different levels was something Tim was keen to look at as mentioned ^

pact544
2022-01-25 18:28
I like the idea of the formatting being exactly the same. The output from the CLI is a decent layout and the colours are good, and I wouldn't want different libraries to do it different ways. If that output was available via the FFI (hopefully with detecting whether the terminal supports colours or not) and not interleaved with the actual logging, that would be my ideal

mike.geeves064
2022-01-25 18:29
Agreed about consistency

mike.geeves064
2022-01-25 18:31
Thinking how you handle the different needs of stdout vs file The other use case Tim was talking about was there's trace level for a Pact user but potentially Trace for a maintainer might want visibility of more under the hood internals, which you might want to see separately/differently etc

mike.geeves064
2022-01-25 18:32
I was thinking it could work if everything is a log, then client side you have control over yes print with normal log timestamps/prefix or not

matt.fellows
2022-01-25 22:59
hmm, strange. I can?t see why the http library used for that wouldn?t set those headers

matt.fellows
2022-01-25 23:03
I wonder if because we use a builder to construct the state change request and specify the headers, that it won?t automatically add the others: https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_verifier/src/provider_client.rs#L84-L97

matt.fellows
2022-01-25 23:03
@uglyog any ideas?

matt.fellows
2022-01-26 03:26
Right, so yes, `println!` is never going to solve the problem you have. I think I saw a discussion elsewhere about getting a response from the verification process that contains fine grained assertion information (as is the case with the current Ruby version, with `--format json` enabled). This would be nice, especially if we could also add a standard output message to print that formats it the same across libraries. This would be separate to the logging output, which would then also solve log problem. What do you think about that? I think it would just be a matter of collecting all of the `println!` into a separate buffer, and in CLI mode just printing it out, and library mode returning the buffer (perhaps in a structured format, to allow for fine grained test output in due course)?

matt.fellows
2022-01-26 03:26
FYI it?s a public holiday here in Australia, so hence the relative quiet yesterday, today and possibly tomorrow

pact544
2022-01-26 08:00
Yeah I think we need to really think about those 2 use cases. Users of the end client library (pact-net, pact-js, etc) first want a summary of the actual interactions and whether they passed or failed. Almost always, this is enough to know exactly what you need to do to fix it (e.g. the failure will say the response had a certain field, whereas the interaction expected another). I think this should be consistent across languages, and effort put in to make it really readable (I think the existing format isn't bad in that regard). They _may_ want some more fine-grained detail about what the library actually did, but probably not. As long as they know which URL was called and what the mismatch is, I think that's pretty much all you need. The other use case is for the library maintainers themselves, and probably really only the core/FFI maintainers. This will be for times when the interaction is passing/failing but it shouldn't be, and so the end-user can't fix it. This would indicate a bug in core/FFI and that's when we'd need the more detailed logs. From typing that, I think I've convinced myself that those logs shouldn't be 'on by default', and instead it's the type of thing where we'd request further info in a bug report (like "please enable this flag and then send the output"). I also think the end-user logs shouldn't have things like timestamps, file sources, log levels etc. etc. on them. The output of that needs to be really clean and readable, and all of those things are just noise that the end-user doesn't really care about.

pact544
2022-01-26 08:50
Tried this out locally in PactNet and it works really nicely :+1:

pact544
2022-01-26 08:51
It appears to only happen when you use the provider states in the query string instead of the body. It's still a `POST` but that should have an accompanying `Content-Length: 0` header

pact544
2022-01-26 08:52
Turns out it's the name and version of the library itself (not provider or consumer). I've fixed it in https://github.com/pact-foundation/pact-reference/pull/173

matt.fellows
2022-01-26 10:56
ah, interesting!

matt.fellows
2022-01-26 10:56
could be a bug in reqwest


matt.fellows
2022-01-26 10:57
Came back to a full inbox, mostly of which is Adam/Pact .NET today - did you fix that issue in the Rust PR?

pact544
2022-01-26 10:59
Yeah I've raised a couple of FFI PRs and done the PactNet mods locally to use them. They're a nice ergonomic improvement there :+1:

matt.fellows
2022-01-26 11:00
I think I?m in agreement with that. Tim had a point that if we buffer logs in the FFI directly and it panics, then we are cooked for debug data, but I think the general UX where all data is buffered and the client can choose how/when to print makes the most sense

matt.fellows
2022-01-26 11:01
oh, that?s awesome. Thank you

mike.geeves064
2022-01-26 11:01
I was going to share the starting point sheet I looked at but I just checked and it's not very helpful for explanation anyway :joy: What I was thinking was to try and do a crude side by side across the different languages of how log output typically looks, and "end users want to see a normally, end users want to see b with debug, maintainers want to see c normally, maintainers way to see d with debug", vs what currently happens

matt.fellows
2022-01-26 11:02
There?s a lot happening in Pactflow town at the moment, hopefully Ron can take a look in the next couple of days. Will the change require changes for @tien.xuan.vo ?

matt.fellows
2022-01-26 11:02
yep, that makes sense

matt.fellows
2022-01-26 11:03
we want each language to be as idiomatic as possible. .NET is definitely a blind spot for a few core maintainers, so having Adam/Yann advocate and be part is very helpful

mike.geeves064
2022-01-26 11:03
as always happens I think when I started to look, first there were problems with me trying JS (which Tim nicely fixed but I'd run out of time) followed by as I was looking at logs I noticed a FFI bug of sending the provider state destroy when it shouldn't be so I did that instead :joy: tangents!

mike.geeves064
2022-01-26 11:04
yep. the maintainers wanting to see x going into a log file rather than a buffer because panic is a good one

pact544
2022-01-26 11:05
I think so yes, it's a breaking change in the FFI. We may want some more in future, but those are 2 obvious ones which are blockers for PactNet

mike.geeves064
2022-01-26 11:07
[one day I will try and get past just talking about things and actually get onto doing them]

uglyog
2022-01-27 01:06
With reqwest we might need to set an empty body. I'll have a look into that.

uglyog
2022-01-27 03:03
@pact544 I've merged the PRs. I'm going to look at extracting the verification output (this will be separate from the logging), but I will leave the printing it out to stdout because it works nicely in other languages.

uglyog
2022-01-27 03:03
I will also bump the minor version (to 0.2.0) due to the breaking changes

matt.fellows
2022-01-27 03:05
If it helps, I?m happy to have the stdout logs buffered for Pact JS/Go and control the output programmatically (but separately) to the other logs. But yes, printing to stdout is not currently causing issues for them.

pact544
2022-01-27 07:33
Yeah if it prints to stdout also then I think that's gonna cause problems in places like GitHub Actions. That does seem to capture stdout (whereas running locally doesn't) so if it still printed to stdout you'd get all the output twice :open_mouth:

pact544
2022-01-27 07:35
It'd be cool if it could auto-detect whether the terminal was capable of colours or nt as well, and still include the ANSI codes because that's def useful. Or if it can't detect, perhaps provide a flag to force colour on or off so that user's can set it appropriately

pact544
2022-01-27 10:42
The new verifier handles feature behaves differently on different OSs: https://github.com/pact-foundation/pact-net/runs/4964627047?check_suite_focus=true I've written an integration test just to make sure the external bindings work, but it never starts an actual provider API so obviously it should fail (and the test checks that the verification fails). On Windows and Linux that's exactly what it does, but on OSX the verifier tests pass :open_mouth: They can't possibly pass though, because there's no provider running and I've pointed at pact sources that don't even exist (like `http://broker.example.org`). The test also takes 58s to run even though I've set a request timeout of 100ms


matt.fellows
2022-01-28 00:43
FYI - looks like soon the certificate problem with tls-native will be solved in reqwest: https://github.com/seanmonstar/reqwest/pull/1316

pact544
2022-01-28 07:56
Good news :+1: Currently I can't run a single provider test on my machine :D

matt.fellows
2022-01-28 11:35
time to get rid of those 10 year old self-signed certs Adam :laughing:

pact544
2022-01-28 13:02
Just whatever AD is pushing onto my machine I guess :shrug: Or whatever http://ASP.Net dev certs get generated

uglyog
2022-02-01 01:23
I've created a JSON schema to describe the verification results JSON :point_right: https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_verifier/src/verifier-results.schema.json

pact544
2022-02-01 07:45
You might want to put a `v1` in there or something just in case it changes in future

pact544
2022-02-02 08:23
I've tried using the new `pactffi_verifier_output` method and unfortunately ~I just get an empty string from it~ the output is all screwed up by the ANSI colour codes :disappointed: I could only get it to work by running inside a Linux container because of the blocker thing about invalid certs on my machine, but the output just looks like this:

pact544
2022-02-02 09:55
Another problem with that output is that it never shows you the actual response body. For example, consider this output. That doesn't help me in finding out where the problem is because I can't see the actual response body. I tried looking in the logs also and it's not printed there either, it just says "Present" ``` [INFO][pact_verifier::provider_client] Received response: HTTP Response ( status: 200, headers: Some({"date": ["Wed", "02 Feb 2022 08:49:28 GMT"], "server": ["Kestrel"], "transfer-encoding": ["chunked"], "content-type": ["application/json; charset=utf-8"]}), body: Present(356 bytes, application/json;charset=utf-8) )``` The Ruby version outputs the entire message when any interactions fails so you can spot what went wrong.

pact544
2022-02-02 10:51
I've got this working locally by using the default native TLS support in reqwset. Is there any reason we're using rustls instead? This seems to work much better:

matt.fellows
2022-02-02 11:02
Unless something has changed, last I checked, the default wasn?t clever enough to discover your self-signed certificates. We moved so that it would respect the standard openssl env vars (`SSL_CERT_FILE` etc.)


matt.fellows
2022-02-02 11:06
we definitely do want that. I wonder if it?s hidden away in a DEBUG/TRACE level log? It could be made to be printable, I?m sure

pact544
2022-02-02 13:34
I just can't fix this ANSI code thing. I knew that was gonna be a problem. If you feed strings with ANSI codes in them through xUnit then they don't apply when they end up on the actual test output. If I write directly to the console they do (after some kernel calls to enable VT mode on the terminal :open_mouth:), but not via xUnit. At the moment I've literally had to just strip them out with a regex

uglyog
2022-02-02 21:58
I'll add an option to disable the ANSI control codes

uglyog
2022-02-02 23:55
Are you still having issues getting the logs? The request/response details won't be in the console output. I can clean those up, but it won't help if you can't get the logs.

uglyog
2022-02-03 00:03
Hmm, good point.

uglyog
2022-02-03 02:03
Bodies were being logged at trace level. I will change that to debug level.

uglyog
2022-02-03 03:17
I've released 0.2.1 with the following changes: ? req/res bodies are logged at debug level ? `enable_ansi_support` has moved out of `pactffi_init` into a new function `pactffi_enable_ansi_support` ? `pactffi_verifier_output` now has a second parameter `strip_ansi`. If non-zero, the ANSI control codes will be stripped.

matt.fellows
2022-02-03 03:49
what?s the use case for having `pactffi_enable_ansi_support` and the ability to strip them off in the verifier output?

uglyog
2022-02-03 03:51
Trying to cover all the bases. I'm assuming if `pactffi_enable_ansi_support` is not called, there won't be ANSI codes in the output, but in case there are still, then ....

pact544
2022-02-03 07:50
So ANSI support is disabled by default and you need to explicitly enable it?

uglyog
2022-02-03 20:46
On Windows, yes

pact544
2022-02-17 10:01
Question about message pacts - at the moment PactNet writes the pact file (in merge mode) after verifying each interaction, but that seems wasteful. I can't remember why it's done that way though - is it necessary/recommended via the FFI or should the pact file just be written once? I know for request pacts it's necessary because the mock server can only be configured once per verification, but I can't think of a reason why message pacts have that restriction

matt.fellows
2022-02-17 10:05
I can?t remember myself

pact544
2022-02-17 10:07
Yeah I feel like I can make one message pact handle, but lots of message handles, and then just write the pact file once at the end. I suppose it's a bit theoretical though. Even if you write the file 100 times in merge mode it's not exactly gonna destroy performance, it just irks that it's inefficient :joy:

matt.fellows
2022-02-17 10:08
haha yes. It?s plausible to do it that way, I?d need to look at the interface again

matt.fellows
2022-02-17 10:08
Maybe we did it because it was easier to port existing implementations over?

tjones
2022-02-17 13:30
@tjones has left the channel

uglyog
2022-02-18 00:01
With Pact-JVM, some people create a separate test for each interaction. I've seen one with 12 interactions, each a separate test. In that case, it has to merge otherwise they will overwrite each other

pact544
2022-02-18 15:51
Yeah, we do a separate test for each interaction also. The question was more about whether you need to write the pact after each interaction or not, i.e. do I need to do this: ? Create pact handle ? Create message handle ? Verify ? Write pact file ? GOTO 1 or this: ? Create pact handle ? Create message handle ? Verify ? Create message handle ? Verify ? Create message handle ? Verify ? Write pact file

matt.fellows
2022-02-20 12:27
Question on the new `pactffi_verifier_*` functions - the `VerifierHandle` appears to be a struct, unlike the other consumer handles which are essentially opaque numbers. Was there a reason this was not done in a similar way?

tien.xuan.vo
2022-02-28 06:23
Do I need to create an issue for this?

uglyog
2022-02-28 06:24
Yes, otherwise it will be forgotten


matt.fellows
2022-03-09 07:58
Looking at adding message pact into the v3 branch of Pact JS. I can see a number of methods that deal with `MessagePactHandle` e.g. (`pactffi_new_message_pact`) and others that use `PactHandle` and `MessageHandle` (e.g. `pactffi_new_async_message`) I?m assuming the latter are to do with v4 pacts where they can be attached, and the former v3?

pact544
2022-03-09 08:21
Hopefully the PactNet implementation could shed some light on that? MessagePactHandle definitely represents the entire pact, whereas MessageHandle is just an individual interaction, but yeah I don't get why PactHandle has got involved there. Perhaps it's a typo but it just work anyway, given they're essentially the same two objects and they're just integer IDs basically

matt.fellows
2022-03-09 08:31
Thanks, I should check the underlying implementation but looking at the C headers it's hard to see which ones to use and why

uglyog
2022-03-09 21:19
The original PR introduced the V3 message Pact, so that might be causing the confusion. `PactHandle` represents the Pact file (whether V3 or V4). `MessagePactHandle` is a V3 message Pact. `MessageHandle` is an interaction.

matt.fellows
2022-03-09 23:08
Cool thx. So I should use the new ones then on the Pacthandle?


matt.fellows
2022-03-14 03:06
I?m still a little confused. I can see that the async methods still return a `MessageHandle` (so the related message functions are still available) but the `pactffi_new_sync_message_interaction` returns an `InteractionHandle` which seems strange to me because the methods that operate on that are HTTP centric. I can?t see how you would set the request/response components of that?

matt.fellows
2022-03-14 03:08
Ditto `pactffi_new_message_interaction` .

matt.fellows
2022-03-20 02:53
:thread: Thread on plugins :point_down:

matt.fellows
2022-03-20 02:54
First go (spiking Golang) - it works with standard HTTP request/response :tada:

matt.fellows
2022-03-20 02:58
I was thinking how the gRPC plugin would work with the current protobufs one. I?m assuming that `pactffi_interaction_contents` is the interface for a content type plugin, and we?d add a new ffi interface for a transport plugin? i.e. you would want to use these things together, but I can?t see how this interface would support something like gRPC. If that?s the case, then the current PactHandle methods aren?t going to look very sensible. ``` i.UponReceiving("some interaction"). Given("plugin state"). WithRequest("GET", "/protobuf"). WithStatus(200). WithPluginInteractionContents(INTERACTION_PART_RESPONSE, "application/protobuf", protobufInteraction)``` That?s the example Golang plugin test I ran before which worked :ok_hand: But assuming that gRPC would have a separate interface, e.g. `pactffi_plugin_transport` or something? ``` i.UponReceiving("some grpc interaction"). Given("plugin state"). WithPluginTransport("grpc", <some json configuration object?>) WithPluginInteractionContents(INTERACTION_PART_RESPONSE, "application/protobuf", protobufInteraction)```

matt.fellows
2022-03-20 06:40
How do you add metadata to the new message interface on the `PactHandle` that return `InteractionHandle` ? i.e. I?m looking for the replacement for `pactffi_message_with_metadata` on `MessageHandle`

uglyog
2022-03-20 21:49
The Java ans Rust ones work by configuring the interaction as current, then start a mock server from that. The mock server updates the interaction to use a gRPC transport.

matt.fellows
2022-03-20 21:58
So how would I signal to the mock server that it should be a gRPC one, I guess. Is there going to be a new FFI method or is simply adding the plugin enough for the mock server to convert to a gRPC transport?

uglyog
2022-03-20 22:11
I haven't got to the FFI interface yet

matt.fellows
2022-03-20 23:30
One of the primary reasons I?m asking is because I?m trying to figure out what the next iteration of the DSL looks like to JS/Golang. I?ve got some feedback on a builder/type-state DSL, but I think the plugin interface is going to significantly impact that design. Ideally I just do it once. In JS, we added a very JSON-like interface: ```{ state: 'i have a list of projects', uponReceiving: 'a request for projects', withRequest: { method: HTTPMethods.GET, path: '/projects', headers: { Accept: 'application/json' }, }, willRespondWith: { status: 200, headers: { 'Content-Type': 'application/json' }, body: {}, }, };``` This makes it super easy to convert other JSON structures to a Pact interaction. But you can see how the validation on this sort of structure would get super messy with plugins (and indeed, some of the features in v3). I?ll probably preserve it for HTTP pact, but I?d like a more type safe API going forward if possible. e.g. you shouldn?t be able to add an HTTP header to a message pact. Or, if using a different transport, you shouldn?t be configuring other things on the HTTP mock server


lewiscowles
2022-04-18 19:12
has joined #libpact_ffi-users

yousafn
2022-04-29 14:38
has joined #libpact_ffi-users

orbit
2022-05-09 17:51
has joined #libpact_ffi-users

pact544
2022-05-24 19:20
I've just raised a new FFI issue for a breaking change: https://github.com/pact-foundation/pact-reference/issues/196 I think it's really important as we want more and more libraries to be shipping on top of the FFI to have a really good regression test suite at the 'black box' level (i.e. using the FFI library itself from another language) and also to communicate breaking changes really clearly with maintainers. There has been no discussion on this channel about the change beforehand, no impact assessment/statement, no guidance on what to look out for afterwards, and I think we need to fix that. I think we need a more mature process around evolving the FFI and maintainers need to be a big part of that discussion. I just happened to notice that it had made logging unusable, and people are going to come to rely on that because they can't just set a breakpoint in their code or whatever, because it now all crosses an FFI boundary. This is the type of thing we need to discuss beforehand so that maintainers are aware they need to check things after upgrades, and ideally this should be found long before the FFI is released and people start upgrading to it. The big problem with the FFI approach is that the bugs will ultimately be reported at the client library level instead of in `pact-reference` itself. If I would've missed that and shipped it, the bug reports would've been raised against PactNet, even though nothing in PactNet changed and the fix doesn't need to be made to PactNet. This hurts the reputation of PactNet, me personally, and the pact ecosystem as a whole, despite it being something generally outside of my control. I apologise that that's a bit of a rant, but it's very frustrating to be surprised like that and I think we need to define an approach going forwards which prevents those surprises.

pact544
2022-05-24 19:21
Probably one for @yousafn

yousafn
2022-05-24 20:10
Really fair comments @pact544 - Rants are welcome, it is a safe space here. We do need to and have a duty to make sure the developer experience is on point for maintainers, as it can have direct and very real impact on end users who are using our libraries to protect their deployments. Appreciate your eagle eye, and I also noted an issue you raised against the pact-specification today aswell. Will take some time to digest, discuss and get something open arranged for us to attend, collect thoughts, agree a path forward. Apologies for the inconvenience!

matt.fellows
2022-05-24 21:50
There are actually a number of tests/examples for the FFI interface (including some c tests e.g. https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/examples/logging/src/main.c). But I think this behaviour is not included in that. I think it would be a good opportunity to revisit the test strategy here. We have discussed the idea of a BDD suite here that shows what the FFI does (ideally, there is also a standard client BDD test suite we have also that can be used to test each language. This could also work as a nice up-to-date feature matrix table)

marti92
2022-05-24 22:43
has joined #libpact_ffi-users

bethskurrie
2022-05-24 23:03
has joined #libpact_ffi-users

uglyog
2022-05-25 08:21
@pact544 can you please stay on the 0.2.x version. I'll let you know when 0.3.x is ok to use

mike.geeves064
2022-05-25 12:07
(+1 for structured logging! :slightly_smiling_face:)

pact544
2022-05-25 14:41
I don't think structured logging solves the problem, because then that just pushes the problem of parsing and displaying it onto every client library. We want a consistent report in all the client libraries, and our method for that is to do it in the shared FFI. I can't stress enough how important these logs are. I've just migrated a codebase with 2283 consumer tests, where 68 were falling after the upgrade. I had to use the logs extensively because there are a number of breaking changes to track down, and the logs are the only place that give you the info you need to work that out. In my case, most of the failures were because the Ruby library doesn't validate query string parameters whereas the Rust library does. We had a few tests where the client sends a query parameter but the setup didn't include it, so now those tests fail. The logs are the **only** way you can find that out.

mike.geeves064
2022-05-25 16:23
:disappointed: I'm not quite sure where the last year went, I still have on my to-do list progressing looking at how the different libraries get logs and what they look like for useful filtering etc following a conversation with Tim I will actually get time at some point :open_mouth:I struggled a bit with the overhead of getting a similar example for each language to get anything meaningful Getting a bit closer :wave: @yousafn :grinning:

yousafn
2022-05-25 16:50
We might want to find a way to open this discussion up and maybe get some face time together. There appears to be a few collaborators who are existing maintainers, long time contributors, or new contributors who are getting involved in different parts of the estate and would be good to get a round table. I can see some work @lewiscowles has been doing across various repos, so is offering fresh insight with some sensible ideas for long term maintainence which are worth surfacing somewhere. I know this is diverging slightly from the actual logging issue but might allow us to take a wider lense view of the estate as a whole. Just spitballing ? agree on a central place to collab ? Drop in sessions across different tz?s to allow video communication as well as async communication proper Diagram of the dependency graph of doom ? target state ? Gap analysis Definitely worth getting the input and thoughts of other maintainers, contributors and users here as there will be such valuable insight and potential actionable items, that I can help coordinate

yousafn
2022-05-25 17:08
Associated pact-php consumption of ffi thread here https://pact-foundation.slack.com/archives/C9W94PXPY/p1653476185980649 We can save all the prior discussions from this and other conversations/issues over the months/years and move them as they are a bit scattered and reducing context/platform switching or providing a single index is probably key to focusing our cognitive load towards common goals

pact544
2022-05-26 19:58
@matt.fellows @uglyog We were having a discussion about publishing verification results when using non-broker sources https://pact-foundation.slack.com/archives/C9UTHV2AD/p1653469545842399. Someone had asked because the https://docs.pact.io/pact_nirvana recommend that a verification job be invoked with a changed pact URI (linked to the broker), which you then verify via a URL source (not a broker source) and publish the verification results back. The user was surprised that PactNet didn't support this option, but in the thread I explained that you can't publish verification results because you don't know the broker URL (and potentially credentials also). I raised https://github.com/pact-foundation/pact-net/issues/392 and I've already pushed up a draft MR for it, but unfortunately at the moment it can't progress. I've checked the FFI and it doesn't support publishing verification results for anything other than broker sources: https://github.com/pact-foundation/pact-reference/blob/e32caf8defd399029dcdf09c5d9298a1fe71d75a/rust/pact_verifier/src/lib.rs#L1207-L1228 If I call `set_publish_options` on the FFI and add anything other than a broker source then it'll simply not publish anything and log an error instead.

pact544
2022-05-26 20:05
So I think the only safe/robust thing to do if we want to support this (and given the CI/CD guide says it's the recommended way of doing it...) is that the user is forced to specify the broker URL in the publish options at the FFI boundary. We can design nicer library APIs on top of that, but fundamentally you can't just assume the host of the URI is also the host of the broker.

pact544
2022-05-26 20:07
e.g. the broker could be running on a sub-path instead of a dedicated sub-domain, like `https://ci.example.org/broker` , so you can't just extract the host and reuse that. It'd also be very hacky to use some kind of fixed string in the path and take everything up to that path. Pact broker URLs always have `/pacts/` in them somewhere, but you can't just assume that's the only place that'll be. Again, someone could run their broker at `https://ci.example.org/pacts` and now string splitting is just asking for trouble.

rholshausen
2022-05-27 03:16
What do we need to do to resolve these issues? One thing I have been thinking of is splitting out the FFI into it's own repository. That way we could hand it over to this group to manage, and I can step away to focus on other areas. The plugin and gRPC work is now nearly complete (which is what I have been focusing on the last 6 months). I just need to get an example project working via FFI (hence the recent change which required a new function), then there are no more plans to change anything else.

bethskurrie
2022-05-27 06:44
I have answered on the issue.

nuno.frias
2022-06-07 08:25
has joined #libpact_ffi-users

nuno.frias
2022-06-07 11:00
Hello. I don't know if this is the correct venue to ask for help but here we go. I am using `pact-go` and when running the provider verification I am noticing that the test hangs after the call to `libpact_ffi`. ```2022/06/02 13:09:55 [INFO] package libpact_ffi found 2022/06/02 13:09:55 [INFO] checking version 0.3.3 for lib libpact_ffi within semver range >= 0.1.2, < 1.0.0 2022/06/02 13:09:55 [INFO] checking version 0.3.3 of libpact_ffi against semver constraint >= 0.1.2, < 1.0.0 2022/06/02 13:09:55 [DEBUG] 0.3.3 satisfies constraints 0.3.3 >= 0.1.2, < 1.0.0 2022/06/02 13:09:55 [DEBUG] version check completed 2022/06/02 13:10:21 [DEBUG] starting new proxy with opts {http localhost:8080 0 [0x1036d5910] /__setup <nil>} 2022/06/02 13:10:21 [DEBUG] starting reverse proxy on port 49359 2022/06/02 13:10:21 [DEBUG] waiting for port 49359 to become available 2022/06/02 13:10:21 [DEBUG] pact provider verification 2022/06/02 13:10:21 [DEBUG] initialising rust mock server interface 2022/06/02 13:10:22 [DEBUG] waiting for port 49359 to become available 2022/06/02 13:10:24 [DEBUG] executing verifier FFI with args [--file /Users/nunofrias/Documents/repos/entitlement-orchestrator/cmd/pacts/reseller-entitlement-service-entitlement-orchestrator.json --hostname localhost --port 49359 --provider-name entitlement-orchestrator --loglevel trace] Hangs here !``` I proceeded to debug the rust ffi code and found that the exact point where it hangs is in the `make_provider_request` function in `http://provider_client.rs` , more precisely in: ```let response = request.send() .map_err(|err| anyhow!(err)) .and_then(native_response_to_pact_response) .await?;``` More curiously I have also noticed that the first time I run the provider verification after I start the terminal application, it succeeds. Subsequent verifications fails more often than not -- if I restart the command line the verification succeeds. I would dearly appreciate some help as my knowledge of rust is rather basic. Thank you.

matt.fellows
2022-06-07 11:50
Hi Nuno, thanks for diving into this

matt.fellows
2022-06-07 11:51
what would be great to know: ? Does it only do this on certain OS?s (e.g. Mac but not linux)? ? Which version of Pact Go are you running

matt.fellows
2022-06-07 11:52
The ?it works once? makes me wonder if any processes are up and about. For example, when it hangs above, can you send http calls to the provider? eg. `curl localhost:49359` or to the proxied target (the actual provider)?

nuno.frias
2022-06-07 11:54
Hi Matt I am using `go version go1.17.6 darwin/arm64` I am running on Mac OS 12 (and it is an M1 chip) I suspect there are some processes outstanding. I am about to enable `dtruss` (strace equivalent) to try and pinpoint the error.

nuno.frias
2022-06-07 11:55
I can send calls to `localhost:49359` and I see the server responses.

matt.fellows
2022-06-07 11:55
Thanks! What version of pact go?

nuno.frias
2022-06-07 11:57
`v2.0.0-beta.11`

nuno.frias
2022-06-07 11:57
I am using the `v2.x.x` branch.

matt.fellows
2022-06-07 11:58
:thinking_face:

matt.fellows
2022-06-07 11:59
have you got a github actions / some build we can see running that reproduces the issue? Does it only happen on M1 (FYI I?m running an M1)

nuno.frias
2022-06-07 12:02
I don't have a build you can test. What I can do is actually run the examples on pact-go and see if the problem occurs. I'll try on Linux (raspberry py) to see if I can see the issue there.

nuno.frias
2022-06-07 12:02
On it

nuno.frias
2022-06-07 14:18
I managed to reproduce it with the examples in Pact go. I am sending a patch file with some very minor changes to the default examples namely to the provider test. Essentially I am commenting out the ProviderVersion BrokerURL ConsumerVersionSelectors PublishVerificationResults as I am using a local pact file and to simplify this scenario I am bypassing the communication with the broker. I also comment out the StateHandlers bit as it caused the test to hang on the state change rather than on running the actual provider request -- the underlying issue seems identical. To set up the example you only need to: ``` git checkout 2.x.x git pull git apply pact_go_examples.diff cd pact-go/examples go test -run ^TestConsumerV3$ . go test -tags provider -run ^TestV3HTTPProvider$``` I am still working on setting up the GitHub actions (but let me know if the above suffices).

phil.vint
2022-06-07 15:32
has joined #libpact_ffi-users

nuno.frias
2022-06-07 17:01
I should have a github action ready briefly.

nuno.frias
2022-06-07 19:41
Here it is. This project contains a minimal example. Apologies for taking this long, I am not used to github actions. https://github.com/nsfrias/pact-go-issue-repro-20220607

nuno.frias
2022-06-07 19:42
As of now I am still waiting for the results of the `macos-12` (which I hope behave similarly to my Mac). https://github.com/nsfrias/pact-go-issue-repro-20220607/actions/runs/2456922279

nuno.frias
2022-06-07 19:43
In ubuntu the issue does not occur.

matt.fellows
2022-06-07 22:57
Thanks Nuno. I can see that it worked on linux too, but the mac build is hanging :man-shrugging:

nuno.frias
2022-06-08 12:47
I am having difficulty running the build against even a x86 macos https://github.com/nsfrias/pact-go-issue-repro-20220607/runs/6793692978?check_suite_focus=true Would it be possible for you to install the project locally on an M1 platform and run the test?

nuno.frias
2022-06-08 13:10
I added some manual reproduction steps on the README

slacksync
2022-06-08 17:22
has joined #libpact_ffi-users

matt.fellows
2022-06-09 05:56
```? /tmp git clone https://github.com/nsfrias/pact-go-issue-repro-20220607.git Cloning into 'pact-go-issue-repro-20220607'... remote: Enumerating objects: 63, done. remote: Counting objects: 100% (63/63), done. remote: Compressing objects: 100% (31/31), done. remote: Total 63 (delta 22), reused 48 (delta 11), pack-reused 0 Receiving objects: 100% (63/63), 26.85 KiB | 8.95 MiB/s, done. Resolving deltas: 100% (22/22), done. ? /tmp cd pact-go-issue-repro-20220607 ? pact-go-issue-repro-20220607 git:(main) go install http://github.com/pact-foundation/pact-go/v2@2.x.x go: downloading http://github.com/pact-foundation/pact-go/v2 v2.0.0-beta.11.0.20220607035712-b017cad30d3d ? pact-go-issue-repro-20220607 git:(main) pact-go -l DEBUG install 2022/06/09 15:54:22 [INFO] package libpact_ffi found 2022/06/09 15:54:22 [INFO] checking version 0.3.2 of libpact_ffi against semver constraint >= 0.3.0, < 1.0.0 2022/06/09 15:54:22 [DEBUG] 0.3.2 satisfies constraints 0.3.2 >= 0.3.0, < 1.0.0 2022/06/09 15:54:22 [INFO] package libpact_ffi is correctly installed 2022/06/09 15:54:22 [DEBUG] skip checking ffi version() call because FFI not loaded. This is expected when running the 'pact-go' command. ? pact-go-issue-repro-20220607 git:(main) go test -run "^TestConsumerV3$" consumer_test.go go: downloading github.com/stretchr/testify v1.7.2 go: downloading github.com/golang/protobuf v1.3.3 ok command-line-arguments 0.846s ? pact-go-issue-repro-20220607 git:(main) go test -timeout 30s -run "^TestV3HTTPProvider$" . ok example.com/m 3.618s ? pact-go-issue-repro-20220607 git:(main) go test -v -timeout 30s -run "^TestV3HTTPProvider$" . === RUN TestV3HTTPProvider 2022/06/09 15:55:26 [INFO] package libpact_ffi found 2022/06/09 15:55:26 [INFO] checking version 0.3.2 for lib libpact_ffi within semver range >= 0.1.2, < 1.0.0 2022/06/09 15:55:26 [INFO] checking version 0.3.2 of libpact_ffi against semver constraint >= 0.1.2, < 1.0.0 2022/06/09 15:55:26 [DEBUG] 0.3.2 satisfies constraints 0.3.2 >= 0.1.2, < 1.0.0 2022/06/09 15:55:26 [DEBUG] version check completed 2022/06/09 15:55:26 [DEBUG] starting new proxy with opts {http localhost:8111 0 [0x4390e60 0x4391160 0x461c1c0] /__setup <nil>} 2022/06/09 15:55:26 [DEBUG] starting reverse proxy on port 64647 2022/06/09 15:55:26 [DEBUG] waiting for port 64647 to become available 2022/06/09 15:55:26 [DEBUG] pact provider verification 2022/06/09 15:55:26 [DEBUG] initialising rust mock server interface 2022/06/09 15:55:26 [DEBUG] waiting for port 64647 to become available 2022/06/09 15:55:26 [DEBUG] executing verifier FFI with args [--file /tmp/pact-go-issue-repro-20220607/pacts/PactGoV3Consumer-V3Provider.json --hostname localhost --port 64647 --provider-name V3Provider --loglevel trace] Given User foo exists WARNING: State Change ignored as there is no state change URL provided 2022/06/09 15:55:28 [DEBUG] HOOK request filter 2022/06/09 15:55:28 [DEBUG] http reverse proxy received connection from [::1]:64653 on path /foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:28 [DEBUG] setting proxy to target 2022/06/09 15:55:28 [DEBUG] incoming request /foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:28 [DEBUG] outgoing request to target http://localhost:8111/foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:28 [TRACE] proxy outgoing request POST /foobar?baz=bar&baz=bat&baz=baz HTTP/1.1 Host: localhost:8111 User-Agent: Pact Go Content-Length: 76 Accept: */* Accept-Encoding: gzip, deflate Authorization: Bearer 1234 Authorization: Bearer 1234-dynamic-value Content-Type: application/json X-Forwarded-For: ::1 2022/06/09 15:55:28 [TRACE] proxied server response HTTP/1.1 200 OK Content-Length: 458 Content-Type: application/json Date: Thu, 09 Jun 2022 05:55:28 GMT { "accountBalance": 123.76, "datetime": "2020-01-01", "equality": "a thing", "id": 12, "itemsMin": [ "thereshouldbe3ofthese", "thereshouldbe3ofthese", "thereshouldbe3ofthese" ], "itemsMinMax": [ 27, 27, 27, 27, 27 ], "lastName": "Sampson", "name": "Billy", "superstring": "foo", "arrayContaining": [ "string", 1, { "foo": "bar" } ] } 2022/06/09 15:55:28 [DEBUG] executing after hook 2022/06/09 15:55:28 [DEBUG] HOOK after each Given User foo exists WARNING: State Change ignored as there is no state change URL provided 2022/06/09 15:55:28 [DEBUG] HOOK request filter 2022/06/09 15:55:28 [DEBUG] http reverse proxy received connection from [::1]:64656 on path /foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:28 [DEBUG] setting proxy to target 2022/06/09 15:55:28 [DEBUG] incoming request /foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:28 [DEBUG] outgoing request to target http://localhost:8111/foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:28 [TRACE] proxy outgoing request POST /foobar?baz=bar&baz=bat&baz=baz HTTP/1.1 Host: localhost:8111 User-Agent: Pact Go Content-Length: 76 Accept: */* Accept-Encoding: gzip, deflate Authorization: Bearer 1234 Authorization: Bearer 1234-dynamic-value Content-Type: application/json X-Forwarded-For: ::1 2022/06/09 15:55:28 [TRACE] proxied server response HTTP/1.1 200 OK Content-Length: 458 Content-Type: application/json Date: Thu, 09 Jun 2022 05:55:28 GMT { "accountBalance": 123.76, "datetime": "2020-01-01", "equality": "a thing", "id": 12, "itemsMin": [ "thereshouldbe3ofthese", "thereshouldbe3ofthese", "thereshouldbe3ofthese" ], "itemsMinMax": [ 27, 27, 27, 27, 27 ], "lastName": "Sampson", "name": "Billy", "superstring": "foo", "arrayContaining": [ "string", 1, { "foo": "bar" } ] } 2022/06/09 15:55:28 [DEBUG] executing after hook 2022/06/09 15:55:28 [DEBUG] HOOK after each Given User foo exists WARNING: State Change ignored as there is no state change URL provided 2022/06/09 15:55:29 [DEBUG] HOOK request filter 2022/06/09 15:55:29 [DEBUG] http reverse proxy received connection from [::1]:64659 on path /foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:29 [DEBUG] setting proxy to target 2022/06/09 15:55:29 [DEBUG] incoming request /foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:29 [DEBUG] outgoing request to target http://localhost:8111/foobar?baz=bar&baz=bat&baz=baz 2022/06/09 15:55:29 [TRACE] proxy outgoing request POST /foobar?baz=bar&baz=bat&baz=baz HTTP/1.1 Host: localhost:8111 User-Agent: Pact Go Content-Length: 76 Accept: */* Accept-Encoding: gzip, deflate Authorization: Bearer 1234 Authorization: Bearer 1234-dynamic-value Content-Type: application/json X-Forwarded-For: ::1 2022/06/09 15:55:29 [TRACE] proxied server response HTTP/1.1 200 OK Content-Length: 458 Content-Type: application/json Date: Thu, 09 Jun 2022 05:55:29 GMT { "accountBalance": 123.76, "datetime": "2020-01-01", "equality": "a thing", "id": 12, "itemsMin": [ "thereshouldbe3ofthese", "thereshouldbe3ofthese", "thereshouldbe3ofthese" ], "itemsMinMax": [ 27, 27, 27, 27, 27 ], "lastName": "Sampson", "name": "Billy", "superstring": "foo", "arrayContaining": [ "string", 1, { "foo": "bar" } ] } 2022/06/09 15:55:29 [DEBUG] executing after hook 2022/06/09 15:55:29 [DEBUG] HOOK after each Verifying a pact between PactGoV3Consumer and V3Provider A request to do a foo returns a response which has status code 200 (OK) includes headers "Content-Type" with value "application/json" (OK) has a matching body (OK) Verifying a pact between PactGoV3Consumer and V3Provider A request to do a foo returns a response which has status code 200 (OK) includes headers "Content-Type" with value "application/json" (OK) has a matching body (OK) Verifying a pact between V3Consumer and V3Provider A request to do a foo returns a response which has status code 200 (OK) includes headers "Content-Type" with value "application/json" (OK) has a matching body (OK) === RUN TestV3HTTPProvider/Provider_pact_verification --- PASS: TestV3HTTPProvider (3.10s) --- PASS: TestV3HTTPProvider/Provider_pact_verification (0.00s) PASS ok http://example.com/m 3.663s```

matt.fellows
2022-06-09 05:56
output from `go env`: ``` GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/matthew.fellows/Library/Caches/go-build" GOENV="/Users/matthew.fellows/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/matthew.fellows/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/matthew.fellows/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/Cellar/go/1.18.2/libexec" GOSUMDB="http://sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.18.2/libexec/pkg/tool/darwin_amd64" GOVCS="" GOVERSION="go1.18.2" GCCGO="gccgo" GOAMD64="v1" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/tmp/pact-go-issue-repro-20220607/go.mod" GOWORK="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/gl/c3f3yhws1mg754r_t7l5hfm80000gp/T/go-build2365344512=/tmp/go-build -gno-record-gcc-switches -fno-common"```

nuno.frias
2022-06-10 08:54
Thank you very much

nuno.frias
2022-06-10 08:56
I still encounter the same issue, so does a colleague with M1.

nuno.frias
2022-06-10 08:56
The only difference is the `go env`

matt.fellows
2022-06-10 09:17
Are you running in Rosetta mode or normal? Have you tried both?

matt.fellows
2022-06-10 09:17
Are they work machines or personal? Is it possible there is AV or endpoint security interference?

nuno.frias
2022-06-10 09:17
I am running in normal mode. I have had some issues with rosetta in the past.

nuno.frias
2022-06-10 09:18
Work machines

matt.fellows
2022-06-10 09:20
I wish we could run builds on M1 to create a reproducible environment. Unfortunately there are no real options to do so at the moment

nuno.frias
2022-06-10 09:20
I am trying to run in rosetta mode

nuno.frias
2022-06-10 09:21
That said I manage to workaround the issue by running the tests on a linux VM running on my mac

nuno.frias
2022-06-10 09:25
Btw I add to add another `cgo` config to run pact-go in linux arm64. ```diff --git a/internal/native/lib.go b/internal/native/lib.go index 9ece6b7..d4324ff 100644 --- a/internal/native/lib.go +++ b/internal/native/lib.go @@ -6,5 +6,6 @@ package native #cgo darwin,amd64 LDFLAGS: -L/tmp -L/usr/local/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi #cgo windows,amd64 LDFLAGS: -lpact_ffi #cgo linux,amd64 LDFLAGS: -L/tmp -L/opt/pact/lib -L/usr/local/lib -Wl,-rpath -Wl,/opt/pact/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi +#cgo linux,arm64 LDFLAGS: -L/tmp -L/opt/pact/lib -L/usr/local/lib -Wl,-rpath -Wl,/opt/pact/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi */ import "C"```

nuno.frias
2022-06-10 09:26
Will submit a merge request for that asap

matt.fellows
2022-06-10 09:30
Does it work on Linux arm? I don't think it should, to my knowledge we don't compile for it: https://github.com/pact-foundation/pact-reference/releases/tag/libpact_ffi-v0.3.2

nuno.frias
2022-06-10 09:30
I compiled for it locally

matt.fellows
2022-06-10 09:35
Ah, got it.

matt.fellows
2022-06-10 09:35
Fair enough we can definitely bring that in

nuno.frias
2022-06-10 09:40
I feel sheepish now. I gave it a try with rosetta and it is passing consistently.

nuno.frias
2022-06-10 09:41
Thank you very much for all the help.

matt.fellows
2022-06-10 09:41
But it should be able to work outside of Rosetta. That's a good clue though. I should be able to repro that situation

fabricio.mendes.ti
2022-07-12 16:36
has joined #libpact_ffi-users

robert.henzel
2022-08-09 20:07
has joined #libpact_ffi-users

duynguyenptithcm
2022-08-20 07:25
has joined #libpact_ffi-users

dwalleck
2022-08-27 16:39
has joined #libpact_ffi-users

hazem
2022-08-30 21:52
has joined #libpact_ffi-users

tien.xuan.vo
2022-09-21 16:32
I got one problem with pact plugins: When I verify provider's pacts that required plugins (csv, protobuf), on Linux and Mac, it work fine, but on Windows it hang. It happen on this line https://github.com/tienvx/pact-php/blob/rust-ffi-plugins-downloads/src/PhpPact/Standalone/ProviderVerifier/Verifier.php#L163 As you can see here https://github.com/tienvx/pact-php/actions/runs/3099040342 , all tests *passed* on Linux and Mac. On Windows it *hang* for hours. I have to cancel it manually. Version: ? pact-ffi: 0.3.11 ? pact-csv-plugin: 0.0.3 ? pact-protobuf-plugin: 0.1.13 Pacts: https://github.com/tienvx/pact-php/tree/rust-ffi-plugins-downloads/example/pacts I test again on my Windows machine and the same behavior:

uglyog
2022-09-22 01:17
I have this same problem, and I haven't found the answer to the issue. Can you raise an issue for this?

tien.xuan.vo
2022-09-22 01:19
Sure. I will report to pact-plugins repo


marko.justinek
2022-11-03 00:04
has joined #libpact_ffi-users

orbit
2022-12-01 15:45
has joined #libpact_ffi-users


uglyog
2022-12-05 21:51
Windows has a different convention. For Linux, the .so file has to start with lib otherwise it won't be automatically picked up, I assume OSX is the same.

j3rry.wan9
2022-12-08 06:13
has joined #libpact_ffi-users

hazem
2022-12-10 00:29
:wave::skin-tone-4: all - i'm helping a dev with a failed build relating to a pact test. nothing seems to have changed on our end but got a `dummy` error message.... i hope it's not us. any ideas in thread

hazem
2022-12-10 00:29
```2022/12/10 00:10:51 [DEBUG] pact setup 2022/12/10 00:10:51 [DEBUG] initialising rust mock server interface 2022/12/10 00:10:51 [DEBUG] log_to_stdout res 0 2022/12/10 00:10:51 [DEBUG] pact add V3 interaction 2022-12-10T00:10:51.555975Z ERROR ThreadId(01) pact_ffi::mock_server::bodies: Failed to parse matching rule from JSON - dummy is not a valid matching rule type 2022/12/10 00:10:51 [DEBUG] pact verify 2022/12/10 00:10:51 [DEBUG] mock server starting on address: 127.0.0.1:0 2022/12/10 00:10:51 [DEBUG] mock server running on port: 38365```

hazem
2022-12-10 00:35
```libpact_ffi: libname: libpact_ffi version: 0.3.15 hash: e4babe9bd82761f01f595a9fd31a0eb8```

hazem
2022-12-10 00:36
fwiw, it's just an error showing red and doesnt seem to fail the build.... we noticed this along with another test failure which we just cleaned up

hazem
2022-12-10 00:56
also in libpact_ffi-v0.3.14 according to our builds

matt.fellows
2022-12-10 02:10
That is strange. My guess is it's in Pact Go. I'll check tonight

matt.fellows
2022-12-12 07:03
OK because of reasons, all things that can accept a Matcher need to be JSON serialisable. This meant that plain string values got escaped with a `"` so I must have used a dummy matcher a few years back. It seems like it doesn?t cause a functional issues, but I?ve put in a minor fix that essentially detects a string value there and prevents the additional quotes.

matt.fellows
2022-12-12 07:03
It?s in the latest `2.x.x` that has not been released yet (i.e. tagged)

matt.fellows
2022-12-12 07:04
Would you mind seeing if that makes the issue go away?

hazem
2022-12-12 16:46
yep - i'll take a look this morning.

hazem
2022-12-12 18:27
@matt.fellows - looks good now! I was able to replicate the issue using the prior pact-go 2.x.x version only after updating my local `libpact_ffi` to `0.3.15`. And ultimately verified your fix on the head of branch 2.x.x. Thanks for fixing!

hazem
2022-12-12 19:03
correction, it was `v2.0.0-beta.17.0.20221212070231-76032bbaf2b6` i verified.

matt.fellows
2022-12-12 20:57
Awesome, thank you! I?ll get a new release out in the next couple of days

tien.xuan.vo
2022-12-15 14:57
Am I correct? ? Pact Ruby Standalone support Pact Specification 2.x ? Pact Rust FFI support Pact Specification 2.x, 3.x, 4.x

yousafn
2022-12-15 15:27
AFAIK ? Pact Ruby Standalone support Pact Specification 1, 1.1, 2.x ? Pact Rust FFI support Pact Specification 1, 1.1, 2.x, 3.x, 4.x ? or at least you can specify them all. https://github.com/pact-foundation/pact-reference/blob/dbe569502561c7d300e2bc428e3553617d4a838b/rust/pact_ffi/src/models/pact_specification.rs#L24-L36 what that actually means to full end to end support of mix and matching. I would assume that theoretically means anyone on a ruby core backed language cannot verify 3.x/4.x pacts and may have limited support for message pacts

yousafn
2022-12-15 15:31
some languages have the ability to generate 3.x message pacts, like pact-python which still uses the ruby core https://github.com/pact-foundation/pact-python/blob/d87d54bce2ed2f74b0a2bb46314b18541bdb598a/pact/message_pact.py#L42 https://github.com/pact-foundation/pact-message-ruby There is an open ticket on https://github.com/pact-foundation/pact-message-ruby/issues/6 for support in that gem for v3 message support. It might be better to use the ffi via ruby https://github.com/YOU54F/pact-ruby-ffi/blob/main/lib/pact_ruby_ffi.rb


yousafn
2022-12-15 15:43
its been a fun little advent of code style polyglot puzzle game for me

yousafn
2022-12-21 11:17
Hey all! Do we have canonical examples of ffi usage for the lifecycle of ? http v3 pact test ? message v3 pact test ? http v4 pact test ? Message async v4 pact test ? Message sync v4 pact test ? Plug-in v4 pact test Can the FFI deal with creating and verifying v2 pacts as well? If so canonical examples would be great for that. Some examples around certain other lifecycles ? logging ? Error handling ? Pact file writing There is some existing useful examples / docs, I used the PHP ones as my go to to replicate ? canonical examples in c https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_ffi/examples ? Arch https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/ARCHITECTURE.md ? PHP https://github.com/pact-foundation/pact-reference/tree/php_plugins/php/src ? Python https://github.com/pact-foundation/pact-reference/tree/php_plugins/python ? There are other Lang examples in that repo ( c / js / ruby ) I?ve been on a little journey learning about FFI / C interop over that last couple of months as a bit of a side thing, as I didn?t know enough about the low level workings of Pact! https://github.com/YOU54F/hello_ffi

yousafn
2022-12-21 11:19
Also would it be useful to authors to be able to see comparable implementations in each of the languages, either samples of direct usage of the ffi, or usage of the ffi in our existing client libraries ( both official and community ) I?ve thought about pulling these into a docs page with code tabs, so I can easily glance across say pact-js-core / pact-net and the current WIP?s done by community members of pact-PHP and pact-python

uglyog
2022-12-21 22:22
> Can the FFI deal with creating and verifying v2 pacts as well? Yes, it should support all the spec versions as it just wraps Pact-Rust

hazem
2023-01-12 01:10
qq - was there a change to the minimum supported version of glibc for libpact_ffi? it seems like the min was `2.28`, but i'm noticing an old build image that use to fail due to an older glibc now passed. so curious and not complaining.

matt.fellows
2023-01-12 01:12
yep, I think we now support back to 2.24. See also https://github.com/pact-foundation/pact-reference/issues/202

hazem
2023-01-12 01:18
:fbwow: i had no idea - thank goodness for this additional support.

tien.xuan.vo
2023-01-16 01:09
Hi https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/src/mock_server/handles.rs#L1038 Is `{"value": ["2","3"]}` the same with `{"value": ["2","3"], "pact:matcher:type": "values"}` ? In other words: If both `pact:matcher:type` and `pact:generator:type` are missing, and `value` is an array, `pact:matcher:type` will be set to `values` ?

uglyog
2023-01-16 01:19
No, I don't think so.

uglyog
2023-01-16 01:19
Looking at the code, it will just treat it as a normal array

tien.xuan.vo
2023-01-16 01:21
:+1: thanks for the info

tien.xuan.vo
2023-03-07 09:37
Hi, are there any way to disable this log: ```The pact at BROKER_URL is being verified because the pact content belongs to the consumer version matching the following criterion: * latest version from branch 'main' (1.0.0) Verifying a pact between CONSUMER and PROVIDER A get request to /marriages/{id} Given A marriage with id 754992c7-c9b8-44d0-840d-9173497ba6e3 exists Request Failed - One or more of the setup state change handlers has failed A get request to /users/{id} Given A user with id dcd79453-7346-4423-ae6e-127c60d8dd20 exists Request Failed - One or more of the setup state change handlers has failed Failures: 1) Verifying a pact between CONSUMER and PROVIDER Given A marriage with id 754992c7-c9b8-44d0-840d-9173497ba6e3 exists - A get request to /marriages/{id} - One or more of the setup state change handlers has failed 2) Verifying a pact between CONSUMER and PROVIDER Given A user with id dcd79453-7346-4423-ae6e-127c60d8dd20 exists - A get request to /users/{id} - One or more of the setup state change handlers has failed There were 2 pact failures``` I think this log is not affected by these 3 ways: ? `$this->ffi->pactffi_init('PACT_LOGLEVEL');` I think only for mock server, do nothing for verifier ? `$this->ffi->pactffi_init_with_log_level('off');` only print more log, can't disable ? `$this->ffi->pactffi_logger_init();` & `$this->ffi->pactffi_logger_attach_sink('stdout', $this->ffi->LevelFilter_Off);` & `$this->ffi->pactffi_logger_apply();` doesn't work as well Don't get me wrong, this log is very useful. But after I fix the problem in the log, I think I want the output a bit shorter when running the tests.

matt.fellows
2023-03-07 10:48
I don?t think so, as this is the key output that all users must see. It?s not a ?log? message, as such

tien.xuan.vo
2023-03-07 10:49
Thank Matt

uglyog
2023-03-07 22:33
It is not log output, but written to standard out

uglyog
2023-03-07 22:33
There is no level associated with it.

tien.xuan.vo
2023-03-22 16:38
Hi, when working with grpc plugin, I saw this behavior, so I want to discuss about it: At first I call `pactffi_verifier_set_provider_info` , it will create a default provider's transport `{transport: "http", port: None, part: "/", scheme: None}` . Then I call `pactffi_verifier_add_provider_transport` , it will create second provider's transport `{transport: "http", port: 8000, part: "/", scheme: "http"}` . Finally I call `pactffi_verifier_execute` , the result is `false` because it call provider on the wrong port (http://localhost, because it use the first transport, the provider is located at http://localhost:8000) Do you think it's an issue? If yes, I can think of some solutions for it: ? Implement `pactffi_verifier_set_provider_info_v2` that didn't create default provider's transport https://github.com/pact-foundation/pact-reference/compare/master...tienvx:pact-reference:solution-1 ? Don't create the default provider's transport at all https://github.com/pact-foundation/pact-reference/compare/master...tienvx:pact-reference:solution-2 ? When calling `pactffi_verifier_set_provider_info` , set `scheme` to something that will be never used e.g. `scheme=invalid => transport=invalid` https://github.com/pact-foundation/pact-reference/compare/master...tienvx:pact-reference:solution-3 ? Instead of appending new transport, try to find the existing transport with the same name and update port + part + scheme (no code, I don't think I know how to do it properly) Some notes: ? This is why I think this issue is valid: I saw this attribute on provider info's protocol, port and path: `#[deprecated(note = "Use transports instead")]` ? The example with 2 transport with the same name `http` may look strange to you. You may ask: so why don't call `pactffi_verifier_add_provider_transport` at all? Just put the port=8000 in the first call to `pactffi_verifier_set_provider_info` . The answer for this is the note above. ? I need to test calling to `pactffi_verifier_add_provider_transport` because when working with the grpc plugin, I think calling `pactffi_verifier_add_provider_transport` is required so that the provider's verifier can work. The default transport `http` doesn't work with grpc

uglyog
2023-03-22 22:21
I think the actual fix should be that `pactffi_verifier_add_provider_transport` should update the existing entry if it has no port set, and not add the second one. The problem is that if we always update the entry, you can't have two different providers on different ports.

uglyog
2023-03-22 22:24
I need to think through "Don't create the default provider's transport at all". It was added to make the transport entries correspond to the deprecated fields. But maybe it should have a fallback to the deprecated fields, i.e., they are an implicit entry. But this may cause other issues.

tien.xuan.vo
2023-03-23 00:47
Another idea from me is to create new ffi function `pactffi_v`er`ifier_set_provider_tr`ans`ports` with json parameter for example

tien.xuan.vo
2023-03-23 10:59
I think I need help with `verifying service method interaction with a gRPC server` https://github.com/pactflow/pact-protobuf-plugin#service-method-provider I choose to write unit test to verify instead of using `pact_verifier_cli` . This part of the unit test: ```public function testPactVerifyConsumer() { $config = new VerifierConfig(); $config->getProviderInfo() ->setName('protobufProvider') ->setHost('127.0.0.1') ->setScheme('tcp') ->setPort(9001); $providerTransport = new ProviderTransport(); $providerTransport ->setProtocol('grpc') ->setScheme('tcp') ->setPort(9001) ->setPath('/') ; $config->addProviderTransport($providerTransport); if ($logLevel = \getenv('PACT_LOGLEVEL')) { $config->setLogLevel($logLevel); } $verifier = new Verifier($config); $verifier->addDirectory(__DIR__.'/../../../broker/pacts'); $this->assertTrue($verifier->verify()); }``` This is the output: ```Verifying a pact between protobufConsumer and protobufProvider request for calculate shape area (0s loading, 2ms verification) Request Failed - builder error for url (): URL scheme is not allowed Failures: 1) Verifying a pact between protobufConsumer and protobufProvider - request for calculate shape area - builder error for url (): URL scheme is not allowed``` This is part of the log I think it's useful: ```2023-03-23T10:56:35.997068Z INFO ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier: Running provider verification for 'request for calculate shape area' 2023-03-23T10:56:35.997099Z DEBUG ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier: Verifying a synchronous message (request/response) 2023-03-23T10:56:35.997212Z INFO ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier::provider_client: Sending request to provider at 2023-03-23T10:56:35.997230Z DEBUG ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier::provider_client: Provider details = ProviderInfo { name: "protobufProvider", protocol: "tcp", host: "127.0.0.1", port: Some(9001), path: "/", transports: [ProviderTransport { transport: "tcp", port: Some(9001), path: Some("/"), scheme: None }, ProviderTransport { transport: "grpc", port: Some(9001), path: Some("/"), scheme: Some("tcp") }] } 2023-03-23T10:56:35.997244Z INFO ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier::provider_client: Sending request HTTP Request ( method: POST, path: /, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(447 bytes, application/json) ) 2023-03-23T10:56:35.997257Z DEBUG ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier::provider_client: body: {"description":"request for calculate shape area","request":{"contents":{"content":"EgoNAABAQBUAAIBA","contentType":"application/protobuf;message=ShapeMessage","contentTypeHint":"BINARY","encoded":"base64"},"matchingRules":{"body":{"$.rectangle.length":{"combine":"AND","matchers":[{"match":"number"}]},"$.rectangle.width":{"combine":"AND","matchers":[{"match":"number"}]}}},"metadata":{"contentType":"application/protobuf;message=ShapeMessage"}}} 2023-03-23T10:56:35.997298Z DEBUG ThreadId(01) verify_interaction{interaction="request for calculate shape area"}: pact_verifier::provider_client: Native request builder: RequestBuilder { method: POST, url: Url { scheme: "tcp", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("127.0.0.1")), port: Some(9001), path: "", query: None, fragment: None }, headers: {"content-type": "application/json"} ``` Do you know how to solve that error `URL scheme is not allowed` ?

tien.xuan.vo
2023-03-23 12:19
After adding some more debug message and compiling `pact_ffi` , I see the real issue: `transport` is missing from pact file: ```{ "consumer": { "name": "protobufConsumer" }, "interactions": [ { ................. "transport": "grpc" } ], "provider": { "name": "protobufProvider" } }``` How can I add this value to pact file?

yousafn
2023-03-23 12:55
The transport should be in the pact file https://github.com/pact-foundation/pact-reference/blob/9b1b7965f0b97a8c7d11f2d8bb6bbeaa5a79e482/php/pacts/grpc-consumer-php-area-calculator-provider.json#L70-L71 I also noted some odd behaviour with `pactffi_verifier_set_provider_info` & `pactffi_verifier_add_provider_transport` I jotted some comments and experiments when trying to verify both a plugin pact (grpc) and http pact and trying to set the correct transports for both ```// ? // This would be my preferrred option // Set the provider name (which should be used by anything using the verifier_handle, and filter sourced pacts that don't contain name) // add multiple transports. // note pactffi_verifier_set_provider_name does not exist // update_provider_info might work // https://github.com/pact-foundation/pact-reference/blob/cfb2c03f87b3f67464291dd936d0aac555c42c91/rust/pact_ffi/src/verifier/handle.rs#L89 // but is marked as deprecated. // // also worthy of note, if pactffi_verifier_set_provider_info didn't mix with the information used in pactffi_verifier_add_provider_transport // this probably wouldn't be neccessary. $ffi->pactffi_verifier_set_provider_name($handle, 'http-provider'); // note this function doesn't exist (wishlist) $ffi->pactffi_verifier_add_provider_transport($handle, 'http',8000,'/','http'); $ffi->pactffi_verifier_add_provider_transport($handle, 'protobuf',37757,'/','tcp');```

yousafn
2023-03-23 12:56
Looks related to your comments here https://pact-foundation.slack.com/archives/C02BXLDJ7JR/p1679503099374349 will take some time to go through them properly today

tien.xuan.vo
2023-03-23 13:25
How can I forgot these valued comments. Let me check through them. Thanks

tien.xuan.vo
2023-03-23 14:33
I found solution (based on your example): replace `pactffi_pact_handle_write_file` by `pactffi_write_pact_file` . I think because mock server know what transport it's using (by calling `pactffi_create_mock_server_for_transport`), asking it to write pact file will have additional `transport` information. I think this useful information should be mentioned somewhere , at least in the `pact.h` file?

yousafn
2023-03-23 14:40
Ahhh fabulous, glad they were helpful to you, it was your PHP examples that helped me in the first place :smile: I think capturing some of these thoughts maybe in https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/ARCHITECTURE.md or some kind of documentation for consumers of the FFI (being Authors/maintainers of pact client libraries) I love the idea of the reference implementations which really strip away from the client libraries DSLs and show the raw FFI calls for particular scenarioes, which then are easier to translate across to other languages as there is a clear view on what methods/args/ordering is required for said feature

yousafn
2023-03-23 14:42
or in the header file, tbh that is where I read most of the comments, however its harder to get too, as you have to get it from the releases pages. It would also be cool if the pact.h was annotated with the ffi version that it is for, I don't think there is a version in it, so you rely on it being supplied with the shared lib (which the pact client libs take care off but more awk when your testing against diff ffi versions directly)

uglyog
2023-03-23 22:06
Also, tcp is not a valid scheme `setScheme('tcp')`, it should be grpc.

tien.xuan.vo
2023-03-23 23:51
> tcp is not a valid scheme `setScheme('tcp')`, it should be grpc I assume this note is for providerInfo part only. I removed it once I found solution above.

tien.xuan.vo
2023-03-24 00:08
Add a comment about `pactffi_write_pact_file` into the file https://github.com/pact-foundation/pact-reference/blob/php_plugins/php/src/consumer-plugin.php, then create a PR to merge branch `php_plugins` into `master` is another option, but it's less obvious, and only for people who interest in reading PHP code only

tien.xuan.vo
2023-04-04 01:51
There are 5 official log levels mentioned in https://github.com/pact-foundation/pact-specification#logging-in-a-pact-library: ? Error ? Warn ? Info ? Debug ? Trace To turn off log, there is another log level. But what is exactly its name? ? Stub Server (Rust) called it `none` https://github.com/pact-foundation/pact-stub-server#command-line-interface ? While Pact FFI (c header) called it `off` , as in `LevelFilter_Off`, https://github.com/pact-foundation/pact-reference/releases/download/libpact_ffi-v0.4.1/pact.h

uglyog
2023-04-04 01:56
Turning off logging is not really a log level, it is a flag that you do not want any logging. TBH, I don't really see the value of it. Why would you not want to at least see if there is an error?

tien.xuan.vo
2023-04-04 02:06
Sorry I didn't ask about how it work. I just ask about naming because I saw inconsistent in the name. For now I think I can just ignore `none` and `off`

jan.krolikowski
2023-04-07 14:43
has joined #libpact_ffi-users

priyaranjanmudliar
2023-04-19 14:25
has joined #libpact_ffi-users

pact544
2023-05-02 14:29
I'm trying to add v4 support to PactNet and I've got in a real mess when I try to use it for real at work. Not every pact will be upgraded to v4 at once (we can't enforce that), so we'll have a mix of: ? v2 pacts with HTTP interactions ? v3 pacts with HTTP interactions ? v3 pacts with message interactions ? v4 pacts with HTTP and/or message interactions The verifier gets in a serious mess when this happens. It starts sending the HTTP requests to the `/pact-messages` endpoint as if they're async requests, which then fails because obviously those are in a completely different format to what's expected. What am I supposed to do in that situation?

matt.fellows
2023-05-02 22:55
As in, you have a Pact file that has different versioned interactions in them? Or different consumers are on different versions of the pact spec?

pact544
2023-05-03 07:03
The latter, yeah - some consumers have like v2 HTTP pacts and some have v4 pacts, but the verifier picks up the v2 pact and treats all the HTTP interactions like they're messaging interactions and hammers the provider with a bunch of invalid requests

matt.fellows
2023-05-03 07:21
ok that scenario makes sense to me, it sounds like it might be a bug then.

matt.fellows
2023-05-03 07:21
I?m just on a call, but later tonight I?ll see if I can repro in Go/JS or something

pact544
2023-05-03 07:22
Yeah cool. I've started putting together a small example in C# as well, although having it in another language would be even better just to confirm it's not just the way I've implemented something

pact544
2023-05-03 08:32
Looking through the code, I think this is to do with how I've implemented it, but in a way that I think might need a change in the FFI approach. For messaging interactions, there needs to be a REST API running with a `/pact-messages` endpoint available which returns the message body when given a magic string. That's really onerous to put that requirements on everyone using message pacts though, so instead PactNet includes a little API which starts transparently to the user and implements the `/pact-messages` endpoint. The problem is that the FFI expects just one API which does both the 'real' endpoints _and_ the `pact-messages` one, but as I say the burden that places on the user isn't really workable. So PactNet currently calls the `pactffi_verifier_set_provider_info` FFI method and points it at the little built-in messaging API. Problem is that this makes the FFI forward _all_ interactions there as if it's the real API. I think it should work more like the provider states endpoint - when you call `pactffi_verifier_set_provider_state` you can pass in an absolute URL, so in theory the provider states endpoint could be on a totally different API running on a different port (or even a totally different host if you wanted to get crazy). I could really do with a way of running a small built-in API on a different port to the main API and having all the `/pact-messages` calls sent over to that API instead. I can't really mandate that users have to implement that endpoint themselves on their 'normal' API, nor can I write something which adds it on for them.

pact544
2023-05-03 08:34
That approach works fine in v3 messaging pacts btw, because v3 pacts can't contain both HTTP and messaging interactions, so even though HTTP interactions would get forwarded to the `/pact-messages` endpoint and break, in practice they don't because there never are any.

pact544
2023-05-03 08:36
Oh and also it works fine because prior to v4 we mandated that anything using messaging had to have a different name, whereas from v4 we're allowing the same name for both HTTP and messaging interactions. From v4, hitting the pact broker for `Orders API` might give you back v2 HTTP, v3 HTTP and v4 HTTP+Messaging, which is what causes the problem with the in-built messaging handler API

pact544
2023-05-03 08:48
So yeah, if there was some kind of `pactffi_verifier_set_messaging_endpoint` or something which you could provide with an absolute URL and it would call for all messaging interactions, that would solve the problem with consumers that have both HTTP and messaging interactions

yousafn
2023-05-03 08:56
> That's really onerous to put that requirements on everyone using message pacts though, so instead PactNet includes a little API which starts transparently to the user and implements the `/pact-messages` endpoint. This sounds nice, I like your approach to the end user experience, it really showed in the migration from v3 -> v4 Your proposal sounds sensible :slightly_smiling_face: > whereas from v4 we're allowing the same name for both HTTP and messaging interactions. Yeah I actually haven't given that a whirl yet, but yeah that is a key feature > From v4, hitting the pact broker for `Orders API` might give you back v2 HTTP, v3 HTTP and v4 HTTP+Messaging, which is what causes the problem with the in-built messaging handler API Yeah I assumed the pact verifier (whether via FFI or CLI) would just handle this, and therefore my recommendation would be to a user stuck on a v2 ruby-backed provider language but generating v3/v4 specs would be to use the verifier cli. Obviously that involves the user knowing more about the lifecycle and appropriate options, than it neatly wrapped up in the DSL Appreciate you putting together the examples :slightly_smiling_face:

pact544
2023-05-03 08:57
Nah, the verifier CLI would be broken in the same way

yousafn
2023-05-03 08:57
I'll let Ron mull over the implementation detail, as I have many yaks to shave, but sounds good and will be awesome to see this in pact-net

yousafn
2023-05-03 08:59
> Nah, the verifier CLI would be broken in the same way ty for confirming, no-one has mentioned it so far, although a few have mentioned it caused them pain in v3 and below, needing separate named providers for message pacts, I haven't heard anyone mention your comments, so you are probably bleeding edge, just as you had proper use case tests in production. The team (PactFlow engineers) have been thinking about a way we can build up a set of examples for the core features (so v4 multi interaction would be one)

yousafn
2023-05-03 09:00
this should help hopefully maintainers implement in a client, language, and for us hopefully to demonstrate the ffi method lifecycle in some reference implementation examples

yousafn
2023-05-03 09:03
Yeah I mapped the level filter of none when I was playing around, but if a user didn't want logging, they wouldn't call the logger init or apply methods

yousafn
2023-05-03 09:04
> TBH, I don't really see the value of it. Why would you not want to at least see if there is an error? Agreed, you probably at least want errors as a minimum, otherwise might as well just send it to the `/dev/null` in the sky hehe

pact544
2023-05-03 09:08
Say you have an API called `Orders API` with 2 endpoints: ? `POST /api/orders` for creating orders ? `GET /api/orders/{id}` for getting an order by ID and when you create an order, it also sends out a pubsub message to say that an order has been created. That's your provider API. Then you have 2 consumers: ? Basket API - this calls `POST /api/orders` to create the order when a user clicks Buy. It is a v2 or v3 pact with only HTTP interactions ? Fulfillment API - this listens to the pubsub topic for when orders are created, and calls the `GET /api/orders/{id}` endpoint to retrieve the new order details in order to trigger the actual shipping of the order. It's a v4 pact with both messaging and HTTP interactions inside When the Orders API hits the pact broker to perform a verification, it'll get both of those pacts back and start trying to verify them. In order to do that, the Orders API _must_ have an endpoint called `/pact-messages` so that the verifier CLI/FFI can post a magic string to it and get a message body back. The problem is that the real Orders API doesn't have that endpoint, because that's a testing implementation detail. So, instead we create a little built-in API which has that endpoint so the user doesn't have to, and that's running on a different port to the main Orders API. This doesn't work though, either via the FFI or CLI, because you can only supply one URL. Either you give it the real Orders API URL, and then the messaging interactions fail because there's no `/pact-messages` endpoint, or you give it the messaging API URL, and then the regular HTTP interactions fail because it's just a little stub service for handling messaging stuff. So what you really need is to be able to provide two different URLs. One for the 'real' API, where all the HTTP interactions should be sent, and one URL for all the messaging interactions to be handled (which may be different to the HTTP URL, but doesn't have to be). In other languages you can probably monkey-patch the messaging endpoint onto the real API at test time from the test library itself, but you can't do that in quite a few languages. So either the library has to have a little built in API to handle them, or the user has to manually implement that endpoint (which is non-trivial). That situation would've never happened with v3 pacts, because you can't have a pacticipant called `Orders API` which has both HTTP and messaging interactions. They'd have to have different names and be in different pacts files, but from v4 that same name can now contain both, and that's what necessitates something that can handle the two types differently.

pact544
2023-05-03 10:19
I've just found `pactffi_verifier_add_provider_transport` which I _think_ can be used to do what I want above

yousafn
2023-05-03 10:35
https://github.com/pact-foundation/pact-reference/commit/9b1b7965f0b97a8c7d11f2d8bb6bbeaa5a79e482#diff-afeb3e0e20ecfe56b3d0f902c4b4665f9d626d59f87602daaaa7c07de3dba859 now you mention this, it brings back memories of when I first trialled out plugins with Tien's PHP example, there was some oddities, I scattered a brain dump in some code comments, and sure I posted about it somewhere but can't find the issue or slack message about it, popping out for lunch shortly

pact544
2023-05-03 11:09
Yeah so I think adding a transport is the way it would be done, but to do that I'm going to have to make a breaking API change in PactNet no matter what I think. When you create the verifier for the example above then you need to add both a HTTP transport and a messaging transport, but the API of PactNet currently only allows you to do one or the other, because in v3 pacts it wasn't allowed to do both (and I didn't know v4 allowed it at the time I wrote it like a year ago)

tien.xuan.vo
2023-05-05 10:21
@pact544 how did you config verifier to call `/pact-messages` endpoint to get messages to verify? it always call to `/` in my case. absolute path will be `http://my-provider.com/` conpare to your `http://your-provider.com/pact-messages`

pact544
2023-05-05 10:25
You can set a path on the FFI call :+1:

tien.xuan.vo
2023-05-05 10:37
do you remember which FFI call is? I would like to know

matt.fellows
2023-05-05 10:53
> I could really do with a way of running a small built-in API on a different port to the main API and having all the `/pact-messages` calls sent over to that API instead. I can?t really mandate that users have to implement that endpoint themselves on their ?normal? API, nor can I write something which adds it on for them. You?re right, this is part of the guide we need to write for maintainers (this is how it?s done in both JS and Go, and how i?ve recommended others do it. We discussed a callback approach, but trust me (and more so Ron), it makes the FFI much more low level and running an HTTP service is just much simpler to do).

matt.fellows
2023-05-05 10:54
> Yeah so I think adding a transport is the way it would be done, but to do that I?m going to have to make a breaking API change in PactNet no matter what I think. When you create the verifier for the example above then you need to add both a HTTP transport and a messaging transport, but the API of PactNet currently only allows you to do one or the other, because in v3 pacts it wasn?t allowed to do both (and I didn?t know v4 allowed it at the time I wrote it like a year ago) Mind elaborating on why it would be a breaking change in the .NET DSL? In JS/Go, the REST API / proxy is completely transparent to the user. We just register one port for messages and another port for HTTP

matt.fellows
2023-05-05 10:56
> I?ve just found `pactffi_verifier_add_provider_transport` which I _think_ can be used to do what I want above yes, that?s the way around it. In fact, you?ll need to use this if you verify a plugin also because it will use a different scheme (e.g. `grpc`)

matt.fellows
2023-05-05 10:57
This is why we are writing a maintainer guide! The raw ingredients (functions) are all there, but how you mix them together (the recipe) matters

matt.fellows
2023-05-05 10:57
Sorry for this confusion. It almost certainly would be in a thread in this channel, now long lost to history.

pact544
2023-05-05 11:00
I've added an RFC to the PactNet channel to detail why this is a breaking change. I've got it working locally now though with that breaking change

pact544
2023-05-05 11:09
There's both a set provider info call and an add transport call where you can specify a path. You always need to call the provider info one first because that gives you the handle you need for adding more transports

pact544
2023-05-05 11:10
Ideally there'd be a separation between transports and provider info so you can create the handle and set the provider name in one call, then add the transports separately. That would make integrating much easier because otherwise you need loads of conditions in your code

matt.fellows
2023-05-05 11:33
Nice! I had a quick pass now, but it?s late and I?ve already had a negroni. I?ll review with fresh eyes next week, and also compare against JS/Go for inspo

matt.fellows
2023-05-05 11:33
have a great weekend!

matt.fellows
2023-05-05 11:42
Also, thanks Adam - I think this is all really helpful. We should include a section on this (setting up an intermediate API, how to set multiple transports etc.) in the maintainer guide we?re about to pick up, what do you think @uglyog?

tien.xuan.vo
2023-05-05 12:35
I think you are talking about `pactffi_verifier_add_provider_transport` (set protocol to `message`). I think it's clever, I didn't think about this before. Let me try it. Thanks @pact544 :+1:

pact544
2023-05-05 12:38
Yeah the problem is that the set provider info method requires that you supply a transport as well as the actual provider info, so if you're adding more than one transport then the first one needs to call set provider info, and any subsequent ones need to call the method you've referenced there. It's a bit of an annoying interaction model to integrate with because whenever you're adding a transport then you need to know whether it's the first one or not, then call different methods depending on whether it's first or not.

pact544
2023-05-05 12:44
Oh and the argument of set provider info and add transport are in different orders with slightly different meanings :facepalm:

tien.xuan.vo
2023-05-05 14:22
`pactffi_verifier_add_provider_transport` work really well to me :tada: I'm not sure I'm fully understand your problem about order of calling those FFI methods (maybe because I always call `pactffi_verifier_set_provider_info` first so no problem for me?) Anyway, I got another problem with those FFI calls that I asked here https://pact-foundation.slack.com/archives/C02BXLDJ7JR/p1679503099374349. Hope it can help.

tien.xuan.vo
2023-05-05 14:26
This is also a useful information user/contributor want to know, maybe a document for it would be nice (if it's not documented somewhere) FYI @matt.fellows

priyaranjanmudliar
2023-05-07 06:29
Hi, I am getting this error when i try to load the libpact_ffi.so in erlang vm that i got from pact_ffi release page: ```"No driver init in dynamic library"``` I have tried multiple ways to load the pact ffi shared library but getting errors similar to the above one, any help would be appreciated. Thanks in advance!

yousafn
2023-05-07 09:29
you need glue code in Erlang/rust for interoperability see this project for some examples https://github.com/elitau/pact_elixir/blob/master/native/pactmockserver/src/lib.rs search for erlang nif or erlang interoperability

yousafn
2023-05-07 09:30
this uses the mock server rather than the ffi tho

priyaranjanmudliar
2023-05-07 13:44
alright, it seems i have to wrap the already existing `http://lib.rs` s too due to some type mismatches between rustler::nif and the implemented functions.

uglyog
2023-05-07 23:31
Just reading through all this, a maintainer guide would be a way to describe how to deal with this problem.

matt.fellows
2023-05-08 00:37
Good timing then :wink:

matt.fellows
2023-05-08 00:39
Absolutely!

priyaranjanmudliar
2023-05-08 01:32
@matt.fellows now that i followed from what yousaf said, I need to use the pact crates and sort of export these functions as what is known as ?nif? in erlang. I did follow these: 1. https://medium.com/@brucifi/writing-your-first-erlang-nif-in-rust-274374094207 2. https://github.com/elitau/pact_elixir/blob/master/native/pactmockserver/src/lib.rs After following article 1, i was able to build these crates, but when i introduced rustler:init! and rustler::nif macros, i am getting this: ```<<"code">> => #{<<"code">> => <<"E0277">>, <<"explanation">> => <<"You tried to use a type which doesn't implement some trait in a place which\nexpected that trait.\n\nErroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func<T: Foo>(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn some_func<T: Foo>(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func<T>(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function. Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function. It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func<T: fmt::Debug>(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n">>}, <<"level">> => <<"error">>, <<"message">> => <<"the trait bound `anyhow::Error: Encoder` is not satisfied">>,```

priyaranjanmudliar
2023-05-08 01:39
In short I tried this: ```#[rustler::nif(name = "create_mock_server")] pub fn create_mock_server( pact_json: &str, addr: std::net::SocketAddr ) -> anyhow::Result<i32> {```

priyaranjanmudliar
2023-05-08 01:40
but this seems to fail this cargo build process

matt.fellows
2023-05-08 01:48
Hmm I?m not sure having to write and compile rust is the best way to go, I seem to recall there being a different way now

matt.fellows
2023-05-08 01:49
hmm does any of the commentary in https://docs.pact.io/slack/pact-elixir.html help?

matt.fellows
2023-05-08 01:50
Ah, still needed NIF but pre-built (which is good, it would suck that users need a rust runtime to run Elixir)

matt.fellows
2023-05-08 01:59
> Hi all, here is an update on the current status of Elixir bindings as of October 2021, and the next steps for developing the library. *HIGH-LEVEL WORK TO BE DONE* The https://github.com/elitau/pact_elixir library is a community-built implementation of Pact in Elixir. Thank you to @pact-slack for the great work on this library so far! In order to make the library fully-featured, we have these general tasks to complete: ? Change the Elixir FFI implementation (see details below) ? Re-implement consumer-side mocks with new FFI ? Implement provider verification ? Implement messaging equivalents ? Implement other workflows like publishing and downloading pacts from a broker *FFI: PROBLEM AND CONSTRAINTS* The pact_elixir library currently uses a Elixir+Rust library called https://github.com/rusterlium/rustler to create safe bindings between the Elixir wrapper and the Rust reference implementation of Pact. Rustler is a great library for creating interop between the two languages because it minimizes the risks of FFI. However, rustler requires the app developer to have a Rust toolchain installed, and to compile the core Rust code at the same time as the app and the pact_elixir library are compiled. This leads to more system dependencies and slower build performance. The developer should not need to know that the internals of pact_elixir are actually written in a different language. The Elixir and Erlang ecosystem has another FFI concept called NIFs, or Natively-Implemented Functions. Note that NIFs require special instrumentation of the native code in order to communicate properly with the Elixir bindings that are calling in. This does not seem like an ideal solution either, because it requires the pact_elixir library to maintain hand-written shim code in C to add this instrumentation. *FFI: NEXT STEPS* We intend to follow the same approach that pact-js and pact-go now follow: the pact_elixir library should download the FFI bundles for each OS architecture at library publish time, and then link to them using whatever strategy is most unobtrusive to the app developer. We can reuse the pipeline scripts from these other implementations in order to download the bundles. We need to pick an appropriate FFI strategy from the Elixir/Erlang ecosystem to allow a good developer experience. Rustler and handwritten NIF instrumentation do not seem to be good options. Erlang Ports or Port Drivers may be viable options. We may also be able to find a library to automatically *generate NIF bindings around the FFI bundles*, and if this is possible, this may be the best option. I am not very familiar with this part of the Elixir and Erlang ecosystem, so if anyone is more familiar with what is available, please share what you know! Once we have researched and picked the right FFI strategy, we can create the bindings and have a fully-featured Elixir implementation of Pact! *RESOURCES* ? https://github.com/elitau/pact_elixir: Elixir bindings for Pact, let?s focus our efforts to evolve this repo! ? https://hex.pm: package manager for the ecosystem ? https://erlang.org/doc/tutorial/users_guide.html: Erlang Interoperability Tutorial User?s Guide, explains NIFs, ports, port drivers, etc. ? https://sudonull.com/post/97911-How-to-write-your-NIF-in-Elixir: Tutorial on writing NIFs. Note that the C code requires instrumentation, so hand-writing a NIF is likely not our best option. Excuse the bad formatting, but this is where it seemed we landed

matt.fellows
2023-05-08 02:00
I read this as pre-compile NIFs and distribute those to users (to avoid users having to compile rust). So you might be on the right path. It looks like some types need additional traits, which is why the compilation is failing

priyaranjanmudliar
2023-05-08 02:24
@matt.fellows that is what i was initially trying to do, load the pre compiled library (libpact_ffi.so or libpact_ffi.dylib) that the already implemented pact-python, pact-js-core has done, also in the examples in pact-reference pr. But it seems in erlang, it fails to load the library using ```erl_dll:load_driver/2```

priyaranjanmudliar
2023-05-08 02:30
even tried using ```erlang:load_nif/2 ``` but the same error comes as ```no driver init```

matt.fellows
2023-05-08 03:24
sorry, unfortunately I have no experience in erlang/elixir so not sure how to guide you here!

tien.xuan.vo
2023-05-08 04:35
Question to all pact ffi users: Does anyone got this similar errors while testing ffi implementation in Windows Server (from Github Actions)? > Script phpunit --debug -c example/phpunit.all.xml handling the test event returned with error code -1073741819

tien.xuan.vo
2023-05-08 14:01
Here are some related logs:

tien.xuan.vo
2023-05-08 14:02
```thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', C:\Users\runneradmin\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-1.27.0\src\runtime\scheduler\multi_thread\http://worker.rs:884:58 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread '<unnamed>' panicked at 'assertion failed: c.runtime.get().is_entered()', C:\Users\runneradmin\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-1.27.0\src\runtime\http://context.rs:292:17 thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', Script phpunit --debug -c example/phpunit.all.xml handling the test event returned with error code -1073741819``` The error itself is quite random. And these logs are even more random. This is the second time I saw them. So not sure it's related to the error.

uglyog
2023-05-08 23:19
`tokio-1.27.0\src\runtime\scheduler\multi_thread\http://worker.rs:884:58` That's in the Tokio runtime

priyaranjanmudliar
2023-05-09 09:26
@srijan.c can you please help here

srijan.c
2023-05-09 09:26
has joined #libpact_ffi-users

srijan.c
2023-05-09 09:39
load_nif/driver will not be able to load a random .so file. It needs to implement the functions expected by erlang interface. You can write a wrapper layer in C that implements this interface. https://www.erlang.org/doc/apps/erl_interface/ei_users_guide.html


yousafn
2023-05-11 09:35
Did some sleuthing yesterday through `cargo.toml` files and some of the repos I know that consume the ffi. Documented here https://github.com/pact-foundation/devrel/issues/10 There may be more outside our wheelhouse, or some that I've missed The pact-reference (rust) core

priyaranjanmudliar
2023-05-15 04:40
hi there are some functions that are deprecated as per the pact_ffi documentation, but used in pact-reference repo in languages like python. For example: ```## Load pact into Mock Server and start mock_server_port = lib.pactffi_create_mock_server(ffi.new("char[]", json.dumps(contents).encode('ascii')) , b'127.0.0.1:4432',0) print(f"Mock server started: {mock_server_port}")``` `pactffi_create_mock_server` seems deprecated as per the pact_ffi documentation, should i be using this or the function thats mentioned in the documentation - `pactffi_create_mock_server_for_transport` ?

uglyog
2023-05-15 04:50
Use the mentioned function, the deprecated functions will be removed at some time in the future

priyaranjanmudliar
2023-05-15 14:27
the PactHandle that is returned by `pactffi_new_pact` is defined as this in the pact.h file: `typedef uint16_t PactHandle;` The problem is when i am calling `pactffi_create_mock_server_for_transport` with PactHandle as lets say 1 (`uint16_t` ) , it returns me -1 which means `An invalid handle was received. Handles should be created with pactffi_new_pact` Am i missing something here? Thanks in advance Edit: I am writing wrappers for these functions in C, so that I can then finally use Erlang NIFs to call these wrapper functions

yousafn
2023-05-15 14:37
each time you call pactffi_new_pact you get an opaque pointer, which is an incrementing id reference, to a pointer held in pact_ffi's address space. have you called `pactffi_new_pact` and passed the result (which is the interaction handle) to `pactffi_create_mock_server_for_transport`

priyaranjanmudliar
2023-05-15 14:43
I am first creating a new pact with `pactffi_new_pact` , then I am storing the returned value in my erlang code, then again invoking pact_ffi_new_interaction(PactHandle, Description) from my erlang code which then invokes my c code. My sample C code for pact_ffi_new_interaction looks like this: ```static ERL_NIF_TERM erl_pactffi_new_interaction(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { unsigned int len1; enif_get_list_length(env, argv[1], &len1); char *buf1 ; // This is my interaction description buf1 = (char *)malloc(len1 * sizeof(char)); if (!enif_get_string(env, argv[1], buf1, sizeof(buf1), ERL_NIF_LATIN1)) { return enif_make_badarg(env); } int ip; // This is my PactHandle if (!enif_get_int(env, argv[0], &ip)) { return enif_make_badarg(env); } PactHandle pacthandle = ip; InteractionHandle interactionhandle = pactffi_new_interaction(pacthandle, buf1); return enif_make_int(env, interactionhandle); }```

priyaranjanmudliar
2023-05-15 14:44
I think i got your point, I will have to invoke the `pactffi_create_mock_server_for_transport` from where I am creating the `pactffi_new_pact` right ?

priyaranjanmudliar
2023-05-15 14:46
can i not fetch the pacthandle from that int that I am getting in return ?

priyaranjanmudliar
2023-05-15 15:20
okay, i changed the code to typecast the int to PactHandle which i was not doing earlier, now i am getting -3 (the code says mock server could not be started)

priyaranjanmudliar
2023-05-15 18:03
I enabled logging for ffi, it seems i was giving the wrong address unintentionally from my erlang code, thanks @yousafn

yousafn
2023-05-16 11:41
saweet! yeah tip 1 always enable logging :)

priyaranjanmudliar
2023-05-17 09:52
hi all, I was able to use the libpact_ffi library and wrote a C interface on top of that for my erlang code to use ! What do y?all think of this as a pact client for erlang Example usage : ```%% pact-erlang (very pre-alpha phase right now) %% Setup PactRef = pact:create_new_pact(<<"consumer">>, <<"producer">>). InteractionRef = pact:create_new_interaction(PactRef, <<"/users api desc">>). pact:insert_request_path(InteractionRef, <<"GET">>, <<"/users">>). ResponseJsonString = jsx:encode(#{auth_id => 1}). pact:insert_response_body(InteractionRef, <<"application/json">>, ResponseJsonString). pact:insert_response_status(InteractionRef, 200). pact:create_mock_server(PactRef, <<"localhost">>, 1234, <<"http">>). %% Sample test code Users = user:get_users(), %% Verify assertEqual({ok, matched}, pact:verify_pact(1234)). %% Write Pact File pact:write_pact_file(PactRef, "/Users/priyaranjan.m/pacts", 0) %% Cleanup test setup pact:cleanup_pact_setup()```

priyaranjanmudliar
2023-05-17 09:56
1. Not a DSL as other languages have implemented, but I believe very much usable any erlang user who wants to use pact features. 2. Haven?t implemented matchers implementation in a module as of now, but I believe its something that can be used manually using integrationjson.md page

priyaranjanmudliar
2023-05-17 10:00
And this only uses the libpact_ffi.a and the pact.h which will be fetched from pact-reference release page, purely written in erlang and C

priyaranjanmudliar
2023-05-17 10:04
The C interface can also be used for elixir applications too, as elixir and erlang both support NIF

priyaranjanmudliar
2023-05-17 11:48
@matt.fellows this C interface will also solve the problem that you mentioned here in the pact-elixir thread https://docs.pact.io/slack/pact-elixir.html: > As long as Elixr can speak a c interface (which it obviously can, because that is what Rustler ultimately does) and you can add a c compatible library to your package (which it sounds like you can), I?d strongly encourage you move away from having the need for rust on a target machine

matt.fellows
2023-05-17 23:30
Nice! I can?t speak too much for the Erlang idiomatics, but if the user of the package doesn?t need additional dependencies to compile and install native deps, just to run Erlang/Elixir code, then this is worth the effort.

matt.fellows
2023-05-17 23:31
I would encourage making fuctions for the matchers etc., because they are so fundamental

matt.fellows
2023-05-17 23:32
the `insert_<fn>` is a bit different to DSLs in the other languages, i?d encourage you to take a look at the latest .NET / JVM / JS / Go to get an idea

priyaranjanmudliar
2023-05-18 07:42
do you think dsl type syntax is neede here also, or only the naming that needs to change (from insert_<fn> to for example with_request()) ?

priyaranjanmudliar
2023-05-18 07:43
@matt.fellows yes the user will not need any external dependency like rust / rustler.

matt.fellows
2023-05-19 05:15
I?m more interested in keeping the naming of functions similar to other languages. As the vast majority of examples out there today won?t be elixir/erlang, anybody searching for examples of how to do X might encounter e.g. JS, so it?s important they can have some familiarity as the move between languages

priyaranjanmudliar
2023-05-22 10:22
what exactly is the difference between these two ffi lib functions `pactffi_new_interaction` https://docs.rs/pact_ffi/latest/pact_ffi/mock_server/handles/fn.pactffi_new_interaction.html and this `pactffi_given` https://docs.rs/pact_ffi/latest/pact_ffi/mock_server/handles/fn.pactffi_given.html

priyaranjanmudliar
2023-05-22 10:22
both introduces description to the interaction ?

priyaranjanmudliar
2023-05-22 10:23
or is that the pactffi_given is for only introducing provider state description ?

matt.fellows
2023-05-22 10:50
There was some reason for needing it in C++

matt.fellows
2023-05-22 10:50
You can set the description from either method, though

uglyog
2023-05-22 22:43
The way C++ constructors work, you can't pass the description in when the handle is created, so it has to be added later.

uglyog
2023-05-22 22:44
`pactffi_new_interaction` creates a new integration and sets the description. It is probably what you want to do.

matt.fellows
2023-05-29 11:55
Sharing this because Tim is an awesome guy (I met him as a fellow speaker at a conference last year and he's genuinely a great human being) and I thought it would be relevant for anyone looking to learn that and get their hands dirty in the rust core: https://www.linkedin.com/posts/timmcnamaranz_if-youve-been-considering-my-free-how-to-activity-7068880463381098496-GFmS?utm_source=share&utm_medium=member_android

matt.fellows
2023-06-23 12:21
Calling all new and existing maintainers. One of the items raised has been the lack of a comprehensive maintainer guide, to help newcomers and even existing maintainers understand how to navigate the ecosystem, implement the FFI and know the ?definition of done?. I?ve put together a draft ToC of a maintainer guide here :point_right: https://github.com/pact-foundation/docs.pact.io/pull/270 Feedback welcome :slightly_smiling_face: _--_ _You can see the deploy preview here: https://deploy-preview-270--docs-pact-io.netlify.app/implementation_guides/maintainer_

pact544
2023-06-26 10:26
Has there been any progress in separating out setting provider info (like the provider name) and adding the transports in FFI? iirc this is a blocker to releasing PactNet with proper v4 support

matt.fellows
2023-06-26 10:58
hello! Is there a related issue (I know there was a few threads on this and may have missed it)? If you wouldn?t mind raising one, we can get it looked into in the next few weeks

matt.fellows
2023-06-26 11:31
These debug logs for req/responses are much nicer @uglyog! ```2023-06-26T11:29:54.651109Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: ---------------------------------------------------------------------------------------- method: GET path: /product/10 query: None headers: Some({"accept": ["application/json", "text/plain", "*/*"], "user-agent": ["axios/0.27.2"], "authorization": ["Bearer 2023-06-26T11:29:54.591Z"], "connection": ["close"], "host": ["127.0.0.1:52291"]}) body: Empty ----------------------------------------------------------------------------------------```

matt.fellows
2023-06-26 11:32
They stand out so much more

pact544
2023-06-26 14:14
*Splitting provider info and transports* The `pact_verifier_set_provider_info` FFI call (https://github.com/pact-foundation/pact-reference/blob/a3c5db598d18d174fbe53f9293b73820b7793d34/rust/pact_ffi/src/verifier/mod.rs#L142-L157 ) includes adding a default transport when setting up the verifier, but this makes integrating with the FFI awkward for libraries. Since Pact Spec v4, a pact file can now contain both HTTP and message interactions, and this is implemented by adding a transport for both HTTP and messaging via `pact_verifier_add_provider_transport` (https://github.com/pact-foundation/pact-reference/blob/a3c5db598d18d174fbe53f9293b73820b7793d34/rust/pact_ffi/src/verifier/mod.rs#L173-L186). The problem is that when the user is setting up a verifier, they want to specify 3 things: ? The provider name ? The HTTP endpoint ? The messaging endpoint The FFI forces them to treat those as two things instead of three though, because specifying the provider name forces you to supply a transport. This creates an awkward API because there are three possible combinations for setting up a verifier: ? HTTP only ? Messaging only ? Both HTTP and messaging Plus in future there may also be plugin-based transports, which creates a combinatorial explosion. You can kinda deal with this in library code by either storing the name up and only adding it once the user has either specified HTTP or messaging, or you can check if you've already added a transport when you add subsequent ones and call different FFI methods. That's what PactNet does https://github.com/pact-foundation/pact-net/blob/feat/verifier-refactor/src/PactNet/Verifier/PactVerifier.cs#L73-L82 That's an awkward thing that every library developer has to implement though, and they may implement them differently. Instead I'd prefer if the FFI allowed you to specify the provider info without having to specify a transport, and then initialising the verifier and adding the transports are separated and easy to integrate with.

uglyog
2023-06-26 23:05
Good point. The `pact_verifier_set_provider_info` predates the changes required to support multiple ports and protocols for the same provider. It should be deprecated and a replacement added.


matt.fellows
2023-06-26 23:54
On the topic of changes to the FFI and RFC, what are your thoughts on where this documentation change should go? Perhaps it?s a good opportunity to try something out.

priyaranjanmudliar
2023-07-31 08:35
Hi @matt.fellows @yousafn I have a scenario where i created a new pact using a Consumer and a provider, created an interaction and then started the mock server for it. When we cleanup a pact mock server, and again start the pact mock server using https://docs.rs/pact_ffi/latest/pact_ffi/mock_server/fn.pactffi_cleanup_mock_server.html and https://docs.rs/pact_ffi/latest/pact_ffi/mock_server/fn.pactffi_create_mock_server_for_transport.html respectively, does that account for the last interaction that i added ?

yousafn
2023-07-31 11:54
are you asking if the interaction added before starting the mock server, persists after calling pact_cleanup_mock_servers?

priyaranjanmudliar
2023-07-31 12:19
yes

yousafn
2023-07-31 12:48
Having a quick look at the rust code, I don?t think the interactionHandle or PactHandle is cleared, I would need to test, by shutting down a mock server and then starting it against by passing it the same PactHandle

priyaranjanmudliar
2023-07-31 12:49
I did this: 1. created new pact -> generated a new pact handle 2. created new interaction -> generated a new interaction handle 3. Added request and response with this interaction handle 4. started the mock server for this pact handle 5. successfully executed the api and verified it and also called the mock server cleanup function (https://docs.rs/pact_ffi/latest/pact_ffi/mock_server/fn.pactffi_cleanup_mock_server.html) 6. Repeated steps 2,3,4. In step 5, execution of api is successful, but verification fails because it also expects me to execute the previous interaction. For verification i have used this - https://docs.rs/pact_ffi/latest/pact_ffi/mock_server/fn.pactffi_mock_server_matched.html

yousafn
2023-07-31 12:54
the PactHandle and InteractionHandle?s are opaque pointers, so numbers 1,2,3 etc. You may need to generate a new PactHandle and then InteractionHandle, or clear the setup Interaction with `pactffi_pact_interaction_delete` for your existing `PactHandle` post calling `pactffi_mock_server_matched` (and processing any mismatches) I?d need to check some other impls and see what they do

yousafn
2023-07-31 12:55
looks like there is `pactffi_pact_model_delete` for deleting the PactHandle I believe

matt.fellows
2023-08-01 05:05
OK, looking at the code in JS, we actually recreate the `Pact` handle for each individual interaction, using the `pactffi_new_pact` method. @uglyog is this the intended behaviour?

uglyog
2023-08-01 05:15
PactHandle was not designed to be reused

matt.fellows
2023-08-01 05:17
Thanks. This will be useful to add to the developer docs. I reckon a mermaid diagram with a state chart would be super nice here!

priyaranjanmudliar
2023-08-01 08:02
@matt.fellows yes, will be very helpful for someone who is developing pact client for other languages

priyaranjanmudliar
2023-08-01 08:05
thanks a lot everyone for the help though !!

matt.fellows
2023-08-01 08:10
no worries

matt.fellows
2023-08-01 08:10
also thanks for raising, I just realised that the V4 interface in Pact JS _doesn?t_ do what I said the V3 interface does (and have just fixed it).

tien.xuan.vo
2023-08-22 09:24
Did anyone use `pactffi_with_multipart_file` before? Do you know how to use it properly?

tien.xuan.vo
2023-08-22 09:26
I got this weird behavior: > 2023-08-22T09:18:48.367683Z DEBUG tokio-runtime-worker pact_matching: --> Mismatches: [BodyMismatch { path: "$", expected: Some(b"testing"), actual: Some(b"testing"), mismatch: "MIME part 'personal_note': Unable to match 'testing' using ContentType(\"text/plain\")" }]

tien.xuan.vo
2023-08-29 17:47
```2023-08-29T17:30:54.852187Z DEBUG ThreadId(03) pact_matching::matchers: String -> String: comparing 'testing' to 'testing' ==> false cascaded=false matcher=ContentType("text/plain")```

tien.xuan.vo
2023-08-30 04:06
Trace log: ```2023-08-30T03:24:34.450933Z DEBUG ThreadId(03) matches_with{self="testing" actual="testing" matcher=ContentType("text/plain") cascaded=false}: pact_matching::matchers: String -> String: comparing 'testing' to 'testing' ==> false cascaded=false matcher=ContentType("text/plain") 2023-08-30T03:24:34.450936Z TRACE ThreadId(03) pact_matching::matchers: match_values: &str -> &str result=Err(["Unable to match 'testing' using ContentType(\"text/plain\")"]) 2023-08-30T03:24:34.450941Z DEBUG ThreadId(03) pact_matching::binary_utils: Comparing file part 'MimeFile { index: 2, name: "personal_note", content_type: Some("text/plain"), filename: "note.txt", data: b"testing", headers: {"content-disposition": "form-data; name=\"personal_note\"; filename=\"note.txt\"", "content-type": "text/plain"} }' to 'MimeFile { index: 2, name: "personal_note", content_type: Some("text/plain"), filename: "note.txt", data: b"testing", headers: {"content-disposition": "form-data; name=\"personal_note\"; filename=\"note.txt\"", "content-length": "7", "content-type": "text/plain"} }' at path '$.personal_note' -> BodyMismatches({"$": [BodyMismatch { path: "$", expected: Some(b"testing"), actual: Some(b"testing"), mismatch: "Unable to match 'testing' using ContentType(\"text/plain\")" }]})```

tien.xuan.vo
2023-08-30 04:08
`testing` is not equals to `testing` . Sound like a bug to me. What do you think @uglyog ?

uglyog
2023-08-30 04:32
hmm, yeah


joshua.ellis
2023-09-04 04:55
has joined #libpact_ffi-users

jonatan.jaworski
2023-09-04 23:09
has joined #libpact_ffi-users

jonatan.jaworski
2023-09-05 01:06
Hi team! I'm getting the following error when trying to run tests that use Pactnet (v5.0.0-beta.1) in a docker container using a dotnet 6 alpine image (http://mcr.microsoft.com/dotnet/sdk:6.0-alpine): ``` Error Message: System.DllNotFoundException : Unable to load shared library 'pact_ffi' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: Error loading shared library libpact_ffi: No such file or directory``` There are no apk packages for `libpact_ffi` as far as I know, do you know what I could be missing here?

matt.fellows
2023-09-05 01:18
I don?t think we support alpine, because shared library support on Alpine is tricky. To do that, would need to build a shared library for each version of musl and detect it at install time.

jonatan.jaworski
2023-09-05 01:18
Ouch. Fair enough

matt.fellows
2023-09-05 01:19
mm

matt.fellows
2023-09-05 01:19
There is a musl target released here, so you _could_ try it: https://github.com/pact-foundation/pact-reference/releases/tag/libpact_ffi-v0.4.8

matt.fellows
2023-09-05 01:19
But it could die in ways that are hard to describe in advance

jonatan.jaworski
2023-09-05 01:20
It's all good. If there are no plans to support Alpine I should probably just move away from it.

matt.fellows
2023-09-05 01:22
Yeah, it would be recommended. We could probably make that more clear on http://docs.pact.io. I?ll find a space for it. Any thoughts? `glibc` is much better for shared libraries, because it?s API is backwards compatible forever. So we can build against an old version of `glibc` and know it will work on any distribution that contains that early version or any later one. _(Just about to pop out for an appointment, but will check ^^ when I?m back)_

rholshausen
2023-09-05 01:22
Try a Debian based image if you can


hazem
2023-09-28 18:47
:wave::skin-tone-4: - Is anyone familiar with this error? I cant replicate but a colleague has this on an M1 machine locally when running pact verifications tests. I'm curious as to why the reason suggests it's look for the dylib in places where I dont necessarily expect. ```dyld[10799]: Library not loaded: libpact_ffi.dylib Referenced from: <71696BE6-E884-368C-9BB5-72CEEC86D657> /private/var/folders/c6/3v5whjln5kgb0mwyjl8djklh0000gn/T/go-build482239365/b001/contracts.test Reason: tried: 'libpact_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibpact_ffi.dylib' (no such file), 'libpact_ffi.dylib' (no such file), '/Users/redacted/integrations/tests/contracts/libpact_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/redacted/integrations/tests/contracts/libpact_ffi.dylib' (no such file), '/Users/redacted/integrations/tests/contracts/libpact_ffi.dylib' (no such file) ```

hazem
2023-09-28 18:49
we install using this command ```go install http://github.com/pact-foundation/pact-go/v2@latest && pact-go -v -l DEBUG install -f``` which results in something like this: ```2023/09/28 10:49:47 [INFO] downloading library from https://github.com/pact-foundation/pact-reference/releases/download/libpact_ffi-v0.4.5/libpact_ffi-osx-aarch64-apple-darwin.dylib.gz to /usr/local/lib/libpact_ffi.dylib &{} 2023/09/28 10:49:49 [DEBUG] obtaining hash for file /usr/local/lib/libpact_ffi.dylib 2023/09/28 10:49:49 [DEBUG] writing config {map[libpact_ffi:{libpact_ffi 0.4.5 15f5d7aee4067c48ef9dd1c25479157d}]} 2023/09/28 10:49:49 [DEBUG] writing yaml config to file libraries: libpact_ffi: libname: libpact_ffi version: 0.4.5 hash: 15f5d7aee4067c48ef9dd1c25479157d 2023/09/28 10:49:49 [INFO] setting install_name on library libpact_ffi for osx 2023/09/28 10:49:49 [DEBUG] output from command [] 2023/09/28 10:49:49 [INFO] package libpact_ffi found 2023/09/28 10:49:49 [INFO] checking version 0.4.5 of libpact_ffi against semver constraint >= 0.4.0, < 1.0.0 2023/09/28 10:49:49 [DEBUG] 0.4.5 satisfies constraints 0.4.5 >= 0.4.0, < 1.0.0 2023/09/28 10:49:49 [INFO] package libpact_ffi is correctly installed 2023/09/28 10:49:49 [DEBUG] skip checking ffi version() call because FFI not loaded. This is expected when running the 'pact-go' command.```

tien.xuan.vo
2023-10-11 14:03
This scenario https://github.com/pact-foundation/pact-compatibility-suite/blob/main/features/V1/http_consumer.feature doesn't look right to me. ```Scenario: Request with a binary body (negative case) When the mock server is started with interaction 7 And request 7 is made to the mock server with the following changes: | body | | file: spider.jpg | Then a 500 error response is returned And the mismatches will contain a "body" mismatch with error "Actual body [image/jpeg, 30922 bytes, starting with ffd8ffe000104a46494600010101004800480000ffe100ae4578696600004949] is not equal to the expected body [image/jpeg, 28058 bytes, starting with ffd8ffe000104a46494600010101012c012c0000ffe12db64578696600004949]"``` According to document of https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/src/mock_server/handles.rs#L1508C89-L1509C43: > Will use a mime type matcher to match the body. I think the content of the binary file doesn't matter. If we change the content of the binary file, as long as the mime type doesn't change (image/jpeg), the mock server shouldn't consider this as a mismatch . The response code should be 200, not 500.

rholshausen
2023-10-11 22:09
That's a V1 scenario, which is not using any matching rules. Matching rules are added as part of V2, and the content type matcher is V3.

tien.xuan.vo
2023-10-12 01:28
:facepalm2: I didn't think about it

tien.xuan.vo
2023-10-12 01:31
:thinking_face: I did select the specification v1, but the response code is 200, not 500 as expected. Not sure what cause it

matt.fellows
2023-10-12 02:31
> https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/src/mock_server/handles.rs#L1508C89-L1509C43: I _think_ this is V3 only, right Ron? It?s what adds the matcher Ron?s talking about. In V1 (and V2), you wouldn?t use this function directly.

matt.fellows
2023-10-12 02:31
(please confirm that is correct Ron)

rholshausen
2023-10-12 03:07
Yes

tien.xuan.vo
2023-10-12 10:37
I only see 2 options to set the body of the request: ? `pactffi_with_body` ? `pactffi_with_binary_file` If I can't use `pactffi_with_binary_file` , so `pactffi_with_body` is the only option. Does `pactffi_with_body` support binary?

tien.xuan.vo
2023-10-16 15:13
I don't think `pactffi_with_body` support binary. So I updated `pactffi_with_binary_file` to add matching rule conditionally https://github.com/pact-foundation/pact-reference/pull/327

matt.fellows
2023-10-17 05:19
I think there is a way to pass binary data to the other method

matt.fellows
2023-10-17 05:35
The definition of `pactffi_with_body` accepts binary in the `body` attribute ```bool pactffi_with_body(InteractionHandle interaction, enum InteractionPart part, const char *content_type, const char *body);```

matt.fellows
2023-10-17 05:36
In Pact Go, this is used for all body types, including binary. i.e. you can pass byte arrays to this type

rholshausen
2023-10-17 05:38
The main problem is that the type for the body is `const char *` which can't have any zero bytes in it and must be ended with a NULL terminator

matt.fellows
2023-10-17 05:42
Ask me how I know that? (not sure why I made that a TODO)

matt.fellows
2023-10-17 05:43
j/k, the C interface method description explains this: ```... * # Safety * * The content type must be a valid UTF-8 encoded NULL-terminated string. The body pointer must * be valid for reads of `size` bytes, and it must be properly aligned and consecutive. ...```

rholshausen
2023-10-17 05:54
That's the description for `pactffi_with_binary_file`

matt.fellows
2023-10-17 06:01
I might have an old/outdated copy of the `pact.h` vendored in the go repo (it?s not linked to code, but there as a reference. Perhaps it should be removed now)

tien.xuan.vo
2023-10-17 08:04
This is the message I got when using `pactffi_with_body` with binary string: ```2023-10-14T02:55:28.212556Z TRACE ThreadId(01) pact_ffi::mock_server::handles: >>> pactffi_with_body(InteractionHandle { interaction_ref: 65537 }, Request, 0x7f0658eb9360, 0x7f0658f24018) 2023-10-14T02:55:28.212564Z WARN ThreadId(01) pact_ffi: Failed to parse body name as a UTF-8 string: invalid utf-8 sequence of 1 bytes from index 0``` This is why I think it doesn't support binary string. Sorry I forgot to mention it.

matt.fellows
2023-10-17 08:27
How are you calling it?

tien.xuan.vo
2023-10-17 10:48
I'm not sure I understand the question.

yousafn
2023-10-17 11:39
i think Matt means what arguments are you passing to the function, when you get the failure above


tien.xuan.vo
2023-10-17 12:19
```$ffi->pactffi_with_body($interaction, $ffi->InteractionPart_Response, 'image/jpeg', file_get_contents(__DIR__ . '/../../compatibility-suite/pact-compatibility-suite/fixtures/spider.jpg'));```

tien.xuan.vo
2023-10-17 12:20
> 2023-10-17T12:16:40.733118Z WARN ThreadId(01) pact_ffi: Failed to parse body name as a UTF-8 string: invalid utf-8 sequence of 1 bytes from index 0

yousafn
2023-10-17 12:31
ty for the simple reproducer, I will take a look later today after the workshop and see what behaviour

yousafn
2023-10-17 12:32
I think PHP FFI?s interface should add the NULL terminator - some lang?s dont such as deno https://github.com/YOU54F/deno-pact/blob/dbe83e74311263cf93621106803a3468e8e17a95/src/lib/safe-ffi.ts#L20-L24

yousafn
2023-10-17 12:34
as its fine with reading with the content type which is also the same type `const char *`

matt.fellows
2023-10-17 21:43
> Failed to parse body name that?s a bit confusing, what?s ?name? in this context. Might need to improve that error message

tien.xuan.vo
2023-10-23 01:30
I'm trying to match header/query to contain multiple values using ffi call but it doesn't work as I expected.

tien.xuan.vo
2023-10-23 01:31
For header, see this thread

tien.xuan.vo
2023-10-23 01:31
For query, see this thread

tien.xuan.vo
2023-10-23 01:31
FFI call: ```pactffi_with_header_v2($interactionId, $ffi->InteractionPart_Response, 'X-IMPROVED', 0, '{"value":["like","regex","values","arrayContaining"],"pact:matcher:type":"values"}');```

tien.xuan.vo
2023-10-23 01:32
Trimmed pact file: ```{ "consumer": { "name": "matchersConsumer" }, "interactions": [ { "description": "A get request to /matchers", "request": {}, "response": { "body": {}, "headers": { "X-IMPROVED": [ "like", "regex", "values", "arrayContaining" ] }, "matchingRules": { "header": { "$['X-IMPROVED']": { "combine": "AND", "matchers": [ { "match": "values" } ] } } }, "status": 200 }, "transport": "http", "type": "Synchronous/HTTP" } ], "metadata": { "pactSpecification": { "version": "4.0" } }, "provider": { "name": "matchersProvider" } }```

tien.xuan.vo
2023-10-23 01:32
Provider's response header: ```X-IMPROVED: regex, like, values, arrayContaining```

tien.xuan.vo
2023-10-23 01:33
Weird message from provider's verifier: ```Failures: 1) Verifying a pact between matchersConsumer and matchersProvider Given Get Matchers - A get request to /matchers 1.1) includes header 'X-IMPROVED' with value 'like' Expected header 'X-IMPROVED' to have value 'like' but was 'like' Expected header 'X-IMPROVED' to have value 'regex' but was 'regex' Expected header 'X-IMPROVED' to have value 'values' but was 'values' Expected header 'X-IMPROVED' to have value 'arrayContaining' but was 'arrayContaining'```

tien.xuan.vo
2023-10-23 01:50
FFI call: `````` pactffi_with_query_parameter_v2($interactionId, 'pages', 0, '{"value":"1","regex":"\\d+","pact:matcher:type":"regex"}'); ``````

tien.xuan.vo
2023-10-23 01:51
Http client query: ```?pages=2&pages=3```

tien.xuan.vo
2023-10-23 01:51
Trimmed logs about matching rule: ```2023-10-23T01:46:59.767978Z DEBUG tokio-runtime-worker pact_matching: matching_rules: MatchingRules { rules: {QUERY: MatchingRuleCategory { name: QUERY, rules: {DocPath { path_tokens: [Root, Field("pages"), Index(0)], expr: "$.pages[0]" }: RuleList { rules: [Regex("\\d+")], rule_logic: And, cascaded: false }} }} }```

tien.xuan.vo
2023-10-23 01:51
Logs about mismatches: ```2023-10-23T01:46:59.768473Z DEBUG tokio-runtime-worker pact_matching: --> Mismatches: [QueryMismatch { parameter: "pages", expected: "", actual: "3", mismatch: "Expected query parameter 'pages' with value '' but was '3'" }, QueryMismatch { parameter: "pages", expected: "[\"1\"]", actual: "[\"2\", \"3\"]", mismatch: "Expected query parameter 'pages' with 1 value(s) but received 2 value(s)" }]```

tien.xuan.vo
2023-10-23 01:53
Note: I expect *every values* of `pages` are integer, *not* the *first* value. But I think there are no way to make `pactffi_with_query_parameter_v2` ignore the index `0` ,just like how `pactffi_with_header_v2` did: > NOTE: If you pass in a form with multiple values, the index will be ignored.

rholshausen
2023-10-23 22:12
What are you trying to achieve here? That any of the provided values must be present, but in any order?

rholshausen
2023-10-23 22:13
This is the problem `expr: "$.pages[0]"`, there is no way with the FFI params to specify `*` instead of 0

tien.xuan.vo
2023-10-24 01:45
How about updating `pactffi_with_query_parameter_v2` to allow something like this (change value from string to array): ```pactffi_with_query_parameter_v2($interactionId, 'pages', 0, '{"value":["1", "2", ["3"]],"regex":"\\d+","pact:matcher:type":"regex"}');``` then it ignore the index `0`

tien.xuan.vo
2023-10-24 01:49
yes, but let ignore the order for now. I provided the values exactly as expected, in the same order, why I still see that error? Plus, the error is trying to say that 2 exact same string are not equals? e.g. `'like' is not equals to 'like'` ?

rholshausen
2023-10-24 03:00
That is really odd

rholshausen
2023-10-24 03:01
I have never tested `"match": "values"` with headers. It doesn't make much sense using that, as it sets up a type matcher, and headers are all the same type (strings)

rholshausen
2023-10-24 03:02
A regex matcher makes more sense

rholshausen
2023-10-24 03:03
But it does seem to be a bug

tien.xuan.vo
2023-10-24 03:06
If we are allowed to use matchers like `values` or `arrayContaining` for headers, then I will report this bug. If we are NOT allowed, then I think we need a way to prevent this from happening, and show some other errors instead. btw, I will report the bug for now.


rholshausen
2023-10-24 03:34
Can you raise a ticket for it?

tien.xuan.vo
2023-10-24 03:36
sure


rholshausen
2023-10-24 03:51
Thank you!

tien.xuan.vo
2023-10-26 02:05
https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/IntegrationJson.md Is it true that: ? Any matcher can be used with any generator, no restriction? ? Any matcher can have any example value, no restriction (as long as the example value can be JSON encoded)?

rholshausen
2023-10-26 02:36
> Any matcher can be used with any generator, no restriction? Technically, yes, but they should compliment each other, otherwise they won't be useful. For instance if you set a regex matcher with `\d+` and a DateTime generator, that will not make much sense because the generated values will be different to the regex. However, a regex matcher with `\d+` and a RandomInt generator will work well.

rholshausen
2023-10-26 02:38
> Any matcher can have any example value, no restriction (as long as the example value can be JSON encoded)? The example values should represent what the matcher is matching. In the customer facing DSL, this should be validated.

tien.xuan.vo
2023-10-26 03:45
Thanks Ron

tien.xuan.vo
2023-10-26 03:45
> The example values should represent what the matcher is matching. In the customer facing DSL, this should be validated.

tien.xuan.vo
2023-10-26 03:46
If I understand correctly, this suggestion is quite opposite with this suggestion from Matt https://pact-foundation.slack.com/archives/C9VBGLUM9/p1690516277135829?thread_ts=1690472580.471449&cid=C9VBGLUM9

rholshausen
2023-10-26 04:41
Yes, because the DSL layer (what is exposed to the user) has the context on what is trying to be done. The backend Rust API does not have that context, so how can it know whether one matcher is not the correct one to use with another generator.

rholshausen
2023-10-26 04:44
If you have a DSL function `integer(100)`, you can know that the regex matcher `\d+` and RandomInt generator is correct, but the RandomDecimal one is not correct. The backend Rust functions won't know that the operation is about integers.

tien.xuan.vo
2023-10-31 06:20
Because of regex validation, I can't register the `interaction #1` in https://github.com/pact-foundation/pact-compatibility-suite/blob/main/features/V2/http_consumer.feature#L8 because of this exception (from pact-php): > The pattern \w{3}\d{3} is not valid for value a. Failed with error code 0. (PhpPact\Consumer\Matcher\Exception\InvalidRegexException)

tien.xuan.vo
2023-11-03 02:18
I think the simple solution is to provide a way to disable regex validation during running compatibility suite

tien.xuan.vo
2023-11-03 02:30
Use `eachValue` matcher for query parameter. See this thread for more details:

tien.xuan.vo
2023-11-03 02:30
Use `regex` matcher with array of values to match multiple values for query parameter works fine. See this thread https://pact-foundation.slack.com/archives/C02BXLDJ7JR/p1698024666918839

tien.xuan.vo
2023-11-03 02:31
But when I replace `regex` by `eachValue` matcher, it doesn't work as I expected:

tien.xuan.vo
2023-11-03 02:33
Client DSL: ```- 'locales[]' => [ - json_encode($this->matcher->regex(['en-US'], '^[a-z]{2}-[A-Z]{2}$')), - ], + 'locales[]' => [ + json_encode($this->matcher->eachValue(['en-US'], [$this->matcher->regex(null, '^[a-z]{2}-[A-Z]{2}$')])), + ],```

tien.xuan.vo
2023-11-03 02:33
FFI call: ```pactffi_with_query_parameter_v2($interactionId, 'locales[]', 0, '"{"rules":[{"regex":"^[a-z]{2}-[A-Z]{2}$","pact:matcher:type":"regex","pact:generator:type":"Regex"}],"value":["en-US"],"pact:matcher:type":"eachValue"}"');```

tien.xuan.vo
2023-11-03 02:34
Http client's query: ```locales[]=en-US&locales[]=en-AU```

tien.xuan.vo
2023-11-03 02:34
Log: ```2023-10-28T07:21:35.888456Z DEBUG tokio-runtime-worker pact_matching::matchers: String -> String: comparing 'en-US' to 'en-US' ==> false cascaded=false matcher=EachValue(MatchingRuleDefinition { value: "[\"en-US\"]", value_type: Unknown, rules: [Left(Regex("^[a-z]{2}-[A-Z]{2}$"))], generator: None }) 2023-10-28T07:21:35.888506Z DEBUG tokio-runtime-worker pact_matching::matchers: String -> String: comparing '' to 'en-AU' ==> false cascaded=false matcher=EachValue(MatchingRuleDefinition { value: "[\"en-US\"]", value_type: Unknown, rules: [Left(Regex("^[a-z]{2}-[A-Z]{2}$"))], generator: None }) 2023-10-28T07:21:35.888576Z DEBUG tokio-runtime-worker pact_matching: --> Mismatches: [QueryMismatch { parameter: "locales[]", expected: "en-US", actual: "en-US", mismatch: "Unable to match 'en-US' using EachValue(MatchingRuleDefinition { value: \"[\\\"en-US\\\"]\", value_type: Unknown, rules: [Left(Regex(\"^[a-z]{2}-[A-Z]{2}$\"))], generator: None })" }, QueryMismatch { parameter: "locales[]", expected: "", actual: "en-AU", mismatch: "Unable to match '' using EachValue(MatchingRuleDefinition { value: \"[\\\"en-US\\\"]\", value_type: Unknown, rules: [Left(Regex(\"^[a-z]{2}-[A-Z]{2}$\"))], generator: None })" }]```

rholshausen
2023-11-03 02:42
Is it just the example value that is not correct? Can we fix that in the suite, or is it a PHP issue?

rholshausen
2023-11-03 02:45
If we change the regex to `\\w{1,3}\\d{0,3}` it should then work. There may be lots of other issues like that.

tien.xuan.vo
2023-11-03 02:52
The problem is: I think compatibility suite is built with pact-rust in mind. This is one example. In pact-rust, we can simply set the regex matcher, no need to validate the value with it. In pact-php (and probably in other languages), we need to validate the value first before setting the regex matcher. I don't think updating `compatibility suite` is a good idea for now. Just add a simple condition to `pact-php` and call it a day.

tien.xuan.vo
2023-11-03 03:03
To test generators in compatibility suite, I have to use https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/IntegrationJson.md. But there are some difficulties: ? `pact:generator:type` is only optional, `pact:matcher:type` is still required ? Set `pact:matcher:type` to `null` or `integer` is the easiest way ? If I set `pact:matcher:type` to something like `type` , I need to also set `value` , which prevent `pact:generator:type` from working ? But I got these errors `Could not generate a random decimal from null` ? Other generator like `date` , `time` , `datetime` or `boolean` works fine because they don't validate the `value` ? Is this change a good idea: https://github.com/pact-foundation/pact-reference/compare/master...tienvx:pact-reference:force-generator-works-regardless-value-type?expand=1

tien.xuan.vo
2023-11-03 03:05
Is this a bug?

tien.xuan.vo
2023-11-03 11:25
I found a very similar block of code here https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_models/src/generators/mod.rs#L854, so I think it's fine to do like that as well.


rholshausen
2023-11-10 00:15
`EachValue` was written to support ignoring the keys in a map like structure in the body. Only really for JSON objects. It will probably not work with anything else.

rholshausen
2023-11-10 00:15
`EachKey` is the same

joshua.ellis
2023-11-10 01:55
Sorry to revive an old thread, but I've also run across the same issue (which suggests we might need to update the Rust FFI docs, or the FFI itself). I naively tried to also use the `with_binary_file` to pass byte arrays which are invalid UTF-8 sequences. I think it might be worth tracking in a ticket on GitHub (which I'm starting to write now).