matt.fellows
2021-05-14 11:46
has joined #pact-net-development

greg595au
2021-05-14 11:47
has joined #pact-net-development

jacek.helper
2021-05-14 11:47
has joined #pact-net-development

hugo
2021-05-14 11:47
has joined #pact-net-development

tony.foster
2021-05-14 11:49
has joined #pact-net-development

matt.fellows
2021-05-14 11:54
First up, going to re-release the change from the other day as a `3.0.0` , with the async fix from Martin (cool to see that Just Eat are still using Pact!)

greg595au
2021-05-14 12:18
hey matt.. my tests will be a little delayed, but no hurry.. i wil get a grip on C# Rust then gat back to this group

matt.fellows
2021-05-14 12:39
*Update on the Rust work* ? :white_check_mark: the Rust FFI bindings for the provider interface are good to go ? :ok: the FFI bindings for the consumer side are about 80% there (no request matching rules or generators on the headers, query string, path). But by the time the work is done to set up here, the Rust code may be ready. See https://github.com/pact-foundation/pact-go/blob/feat/v3-ffi-verifier/v3/internal/native/mockserver/mock_server.go for the Golang raw FFI boundary.

matt.fellows
2021-05-14 12:39
The provider verifier is almost a drop-in replacement for the current ruby one. You also have two choices in terms of replacing it ? Use the CLI and spawn it (just like the Ruby one, except it would be an executable) ? Use the FFI boundary

matt.fellows
2021-05-14 12:41
It?s also SUPER FAST. In the JS spike I?ve done, this is how fast the test runs: ```? native git:(spike/ffi-provider) ? time node test.js node test.js 0.10s user 0.02s system 102% cpu 0.117 total```

matt.fellows
2021-05-14 12:42
When I showed Tim (another maintainer) he actually went back to the IDE to look for the problem, assuming that it failed so quickly there must have been an obvious code error

matt.fellows
2021-05-14 12:43
Greg - I think we?ll need to get some help from our new contributors for the mocking. Neil is trying to step away, and Beth knows this much C# -> `0`

greg595au
2021-05-15 00:07
lol... fair enough neil wants to step away.....

greg595au
2021-05-15 00:09
using the FFI boundary would have the advantage we can pass results/data/errors back for handling them in the appropriate library. CLI is easier but we get isolated from the run, getting something back requires us to use a headless prompt and read in the stdout and stderr streams

yann.courtel
2021-05-18 09:18
has joined #pact-net-development

yann.courtel
2021-05-18 10:12
Hi. I had a question regarding the version number. Why we upgraded to 3.0.0 since we are not in sync with the pact specs 3.0? Wouldn't it have been more adequate to have a minor version change? => 2.7.0 Thanks

yann.courtel
2021-05-18 10:13
Hi everyone, nice to see we are starting to have some contributors. I will go over the PACT 3.0 specs and see what little time I can get to help. Keep you all posted.

matt.fellows
2021-05-18 10:14
The version of the library is independent of the spec version. There was a breaking change in this version from a semver perspective, which we believe is the appropriate versioning mechanism at this moment. But we should all get together and start to agree on our governing processes. I'll be up on my computer in the next hour and will see how we can find some timea to chat

greg595au
2021-05-18 10:23
hi yann - welcome to the dev corner

yann.courtel
2021-05-18 12:12
ok I understand. That is actually not a bad idea. If I were to start looking at a solution, could I then start with the 3.0.0? To see the feasibility of some features of the 3.0 specs.

matt.fellows
2021-05-18 12:23
Judging by the timezones we have, a 10pm call here in Australia is 8am on the west coast (US/Canada) and 2pm in Central Europe

2021-05-18 12:25
@matt.fellows has a polly for you!

matt.fellows
2021-05-18 12:26
10pm is a pain in the butt Greg, so if you can?t make it, we could schedule another time together

matt.fellows
2021-05-18 12:26
In the meantime, we need to scratch together an agenda

matt.fellows
2021-05-18 12:26
:thread: on an agenda :point_down:

matt.fellows
2021-05-18 12:40
Whipped together a quick document that we can collaborate on: https://docs.google.com/document/d/1I8Ww4v4td5t1d3uNrKEjGAKHnbsR9osBotz5xLMBCqw/edit#

matt.fellows
2021-05-18 12:40
If you could please share an email, i?ll add you all as editors so we can work on this asynchronously

yann.courtel
2021-05-18 12:48
Done. Thanks Matt

tjones
2021-05-19 04:28
has joined #pact-net-development

greg595au
2021-05-19 06:35
Hi matt.. done.. my machine has been a royal pain today.. slack crashed out

matt.fellows
2021-05-19 10:33
Thoughts or feedback?

greg595au
2021-05-19 10:43
hi matt, my "good" machine played up. 25th at 10pm

matt.fellows
2021-05-19 10:54
Thanks Greg!

greg595au
2021-05-19 10:55
everything crashed or threw errors... sheesh.. upgrade is coming

matt.fellows
2021-05-19 10:55
:grimacing:

greg595au
2021-05-19 11:56
On my nachine or the doc?

greg595au
2021-05-19 11:56
I put unit testing and rfc referencing up

matt.fellows
2021-05-25 05:47
So only 2 responses, might need to find another time for all?

matt.fellows
2021-05-25 05:47
@jacek.helper are you keen? Hugo has let me know he can't contribute at this time

matt.fellows
2021-05-25 08:20
@greg595au sorry to do this, but I actually now have a 10pm meeting (my fault for not blocking the calendar, but I was also hoping to get more responses to the above)

matt.fellows
2021-05-25 08:20
@yann.courtel is still keen to join

matt.fellows
2021-05-25 08:20
@yann.courtel are you free up to 1 hour earlier? (i.e. 1pm your local time)

matt.fellows
2021-05-25 08:21
@greg595au is 9pm local time workable? If so, i?ll get an invite out shortly

greg595au
2021-05-25 08:21
Hi matt.. 9 pm works..

matt.fellows
2021-05-25 08:21
Apologies, we only need to align 2 timezones? now. Alternatively, we wait for others to respond to see if it?s worth rescheduling

matt.fellows
2021-05-25 08:21
But I reckon we get cracking

matt.fellows
2021-05-25 08:21
I?ll record and share

yann.courtel
2021-05-25 08:26
Yep. Looks like for me it's 1PM. I'll be there!

matt.fellows
2021-05-25 08:37
:raised_hands:

matt.fellows
2021-05-25 09:17
Anyone wanting to join tonight to discuss the future/roadmap of Pact .NET can join at 9pm AEST / 1pm CET Pact .NET Tuesday, 25 May ? 9:00 ? 10:00 pm Google Meet joining info Video call link: https://meet.google.com/hzm-njxs-kwt Or dial: +61 2 9051 3678 PIN: 497 948 990# More phone numbers: https://tel.meet/hzm-njxs-kwt?pin=4275417422534



matt.fellows
2021-05-25 13:21
(it will be denied by default for those who didn?t attend, but i?ll approve when you try to open as I?ll be notified :stuck_out_tongue: )

jacek.helper
2021-05-25 16:05
Sorry I have missed that plus I have couple of extra things in this week so this way or another it will be hard to still yet another hour from my sleep time. Next week looks more promising to me.


matt.fellows
2021-05-25 22:33
no worries

matt.fellows
2021-05-25 22:34
I?ll aim for some time in the next day or so to document more of what happened. See the main channel for the video recording. The last 30 are about the FFI bindings stuff

pact544
2021-05-26 06:50
has joined #pact-net-development

pact544
2021-05-26 07:00
Hi all - quick update from me about something I'm doing locally. I've started porting from the Ruby implementation to the Rust version via the FFI interface for consumer tests (not provider yet). I get the feeling we may need to make some breaking changes because of the differences between them. For example, the Ruby version supports supplying your own TLS cert but the Rust version appears to only be able to use a built-in self-signed cert but allows you to retrieve the CA programatiicaly so you could technically trust the cert at runtime. We'd either have to remove custom TLS from PactNet or try to add custom TLS to pact-rs instead. Another awkward change which I'm just in the middle of is that the `Path` and `Query` params on the request setup are of type `object` but the Rust implementation wants them supplied in string key/value pairs (with an index as well). At the moment my version supports Path and Query of `string` type (by splitting on `&` and then each segment on `=` for query) and we can definitely support `Dictionary<string, string>`, but I think in the current version lots of people use `dynamic` with an anonymous object. We'd have to use some reflection to retrieve the properties from the `dynamic` I think. You'd have to throw an exception if those params were of any type that we didn't support. Either that or we make a breaking change and stop those two properties on request from being of type `object` and pick something that's easier to support. I'm sure ther are more challenges but those are the two off the top of my head :slightly_smiling_face: I've not got to matchers yet so I imagine there's plenty more trouble headed my way :smile:

matt.fellows
2021-05-26 07:02
cool!

matt.fellows
2021-05-26 07:03
OK so the rust interface for those are fairly low level

matt.fellows
2021-05-26 07:03
The TLS cert is something we can add in later - honestly, using TLS in most cases is just overkill. But we should support it eventually

matt.fellows
2021-05-26 07:03
For version 1, I would consider ignoring completely

pact544
2021-05-26 07:04
Cool I'll drop those args then

matt.fellows
2021-05-26 07:04
Can you please elaborate on the query/path problem?

matt.fellows
2021-05-26 07:05
(we do need a strategy to move forward so we?re not constantly adding breaking changes, but let?s separate the two problems for now)

matt.fellows
2021-05-26 07:06
on the indexed query/header values, it?s because it now supports multiple _values_ for a given key

matt.fellows
2021-05-26 07:06
i.e. if you had `?foo=bar&foo=baz` That could be represented more strictly than the current version. The index is for the array values, so it?s just `0` for others

matt.fellows
2021-05-26 07:06
ditto for headers

matt.fellows
2021-05-26 07:07
But appreciate it is a bit clunky - you would need to map/iterate over any objects that translate to it. So yes, probably breaking change

pact544
2021-05-26 07:08
So the Ruby version can take pretty much any argument for query because it's of type `object`(code https://github.com/pact-foundation/pact-net/blob/c2b8dfeeeebf2312bb37d7c54137802b117720bc/PactNet/Mocks/MockHttpService/Models/ProviderServiceRequest.cs#L20 ) but the Rust FFI interface `with_query` just takes a string key and string value (plus an index so you could repeat query params with the same name)

pact544
2021-05-26 07:09
That's fine for the Ruby one because http://JSON.Net will just serialise that properly if you pass a dynamic object

pact544
2021-05-26 07:09
Like ```Query = new { foo = "bar" }```

pact544
2021-05-26 07:10
But you can also do `Query = "foo=bar&baz=bash"` and just pass it a string, which works also

pact544
2021-05-26 07:11
I imagine you can also pass it a dictionary like the `Headers` property takes, but I've never tried that

matt.fellows
2021-05-26 07:11
yeah, that?s definitely not easily doable now. FWIW the current implementation for query strings is a constant source of issues, so I think the newer version is actually better because it?s more explicit, but it?s different

pact544
2021-05-26 07:12
The problem with having an API of type `object` is we have no idea how consumers are actually using this thing, so trying to support all the current usages is near-impossible. I think we need to either pick a sensible-subset to support, or change from `object` to something more usable for us

matt.fellows
2021-05-26 07:13
in pact-go, I?m moving to a more builder style pattern. You could then over load methods to take different types, and provide better type support etc.

pact544
2021-05-26 07:13
I'd personally prefer some kind of `QueryBuilder` class so that it can internally keep everything as key/value pairs and also support adding the same key multiple times (which eventually ends up as `foo=bar&foo=whatever`

pact544
2021-05-26 07:13
Ha, snap

matt.fellows
2021-05-26 07:13
:slightly_smiling_face:

pact544
2021-05-26 07:14
But yeah, that'd be another breaking change on top of dropping custom TLS

matt.fellows
2021-05-26 07:14
you?ll see a similar conundrum when dealing with bodies. Because it now supports binary payloads/multipart etc. you might want to provide different typed options

matt.fellows
2021-05-26 07:14
e.g. a `.JSON(?)` for json bodies

pact544
2021-05-26 07:15
Yeah at the moment `Body` is just `dynamic` so it can be literally anything and is expected to be JSONified

pact544
2021-05-26 07:15
We'd need that to be like an `IPactBody` and then have different implementations for it, so one for JSON and one for binary

matt.fellows
2021-05-26 07:15
sounds reasonable

matt.fellows
2021-05-26 07:16
One of the challenges at the moment is for users knowing what they can actually put in there.

matt.fellows
2021-05-26 07:16
examples only go so far

pact544
2021-05-26 07:17
Yeah for sure. The current version is super flexible by effectively skipping the type system and delegating the problem to http://Json.Net, but that's not so easy in Rust land where you don't get to defer problems to someone else :smile:

matt.fellows
2021-05-26 07:17
yeah. But it?s not ideal for users either, because they have to work trial and error

matt.fellows
2021-05-26 07:18
A related problem is the v2/v3 problem - you don?t want somebody using a v3 matcher in a v2 test. Ideally, you want the type system to prevent this.

pact544
2021-05-26 07:18
Yep definitely. If we're OK with the idea of making breaking changes there and using the type system more to guide users into the pit of success, I'm all for that

matt.fellows
2021-05-26 07:19
a major upgrade to Rust would warrant a breaking change, but we need general community consensus. A place to consider this is creating a GH issue with an RFC like proposal - keen to submit that?

pact544
2021-05-26 07:19
It starts sounding like a more fundamental rewrite though once you do stuff like that :smile:

matt.fellows
2021-05-26 07:19
well, it may well need it - I?m not sure

pact544
2021-05-26 07:20
Yeah I can submit a proposal. I'll probably carry on with where I am at the moment until I hit an inevitable brick wall, and then write up what I think is best to do next

matt.fellows
2021-05-26 07:20
(I don?t maintain pact .NET but am helping out whilst we build up our new set of maintainers)

matt.fellows
2021-05-26 07:21
The earlier you get it into the public domain the better so we can give feedback/guidance etc., and also ensure somebody else doesn?t waste their time doubling up

pact544
2021-05-26 07:32
I have a very very early version available here: https://github.com/adamrodger/pact-net/tree/feature/rust-interop In the middle of adding the query support

matt.fellows
2021-05-26 08:38
cool - have you tackled matchers yet?


matt.fellows
2021-05-26 08:39
I?m aiming to publish some guidance in the next week about what matchers can go into places, and the JSON structure you can give the FFI



matt.fellows
2021-05-26 08:41
JSON structure looks like this: ```{ 'pact:matcher:type': 'type', value: [template], }```

pact544
2021-05-26 12:37
So the API I've got to at the moment now looks like this for consumer tests (with matchers not done yet) using the Rust FFI integration internally and maintaing support for using a remote service: ```[Fact] public async Task GetAllEvents_WithNoAuthorizationToken_ShouldFail() { var config = new PactConfig { SpecificationVersion = "2.0.0", DefaultJsonSettings = new JsonSerializerSettings(), /* ... set whatever ... */ LogDir = "./logs", PactDir = "./pacts", Overwrite = true }; IInteractionBuilder interactions = new PactBuilder(config).ServiceConsumer("consumer") .HasPactWith("provider") .UsingNativeBackend(8080, IPAddress.Any); // or .UsingRemoteBackend(new Uri("http://remote.example.org"); var interaction = interactions .UponReceiving("a request to retrieve all events with no authorization") .Given("there are events with ids '45D80D13-D5A2-48D7-8353-CBB4C0EAABF5'") .WithRequest(HttpMethod.Get, "/events") .WithHeader("Accept", "application/json") .WillRespond() .WithStatus(HttpStatusCode.Unauthorized) .WithHeader("Content-Type", "application/json; charset=utf-8") .WithJsonBody(new { message = "Authorization has been denied for this request." }); var consumer = new EventsApiClient(_mockProviderServiceBaseUri); await Assert.ThrowsAnyAsync<Exception>(() => consumer.GetAllEvents()); interaction.Verify(); }```

pact544
2021-05-26 12:38
The fluent API ensures that you can't try to configure the request/response out of order and stuff, effectively using the typestate pattern

pact544
2021-05-26 12:42
I think we'd distribute the FFI stuff as a NuGet using the `native/` layout and then NuGet will automatically restore the env-specific FFI libraries without that stuff having to pollute the PactNet core code. I've also separated out the "backend provider" so we could keep supporting the Ruby version, the Rust native version and the remote version all in one package. Or we could ship like a `PactNet.Providers.Native` and `PactNet.Providers.Remote` etc in the same way you have things like `Microsoft.Extensions.Configuration.Json` shipping custom providers on top of a library with the core logic that's provider-agnostic

matt.fellows
2021-05-26 12:46
Great progress!!

matt.fellows
2021-05-26 12:47
One comment I?ll make (and I say this without much knowledge of the nuget ecosystem). Ideally, we bundle the rust package into the artifact. We get a lot of complaints from enterprises behind proxies when dependencies need to be downloaded dynamically during instnall (e.g. pulling a release down from GH releases). I don?t think you?re proposing it, but _just in case_

pact544
2021-05-26 14:07
Yeah it'd be bundled up with a NuGet, which matches how it works now. Currently you need to install `PactNet` and also like `PactNet.Windows` because that contains the Ruby dependencies. I'm proposing we ship a single `PactNet.Native` instead of one per OS which contains all native deps. NuGet will unpack the correct one at build time depending on the OS (it's a single nuget with like `native/win-x64/mock_server_ffi.dll` inside it, with a path per binary)

pact544
2021-05-26 14:09
Anyway, I've pushed an updated version which now actually manages to call the Rust mock server, can recognise failed interactions and does all the appropriate unmanaged cleanup stuff. However, it keeps thinking every request is unexpected so there's probably some kind of issue there (I assume it's mismatched headers?) If you want to build it locally you'll have to unload the unit tests as I've not sorted those yet. Wanted to make sure we agree on the API/layout before spending too much time on them. The samples compile though. Branch here: https://github.com/adamrodger/pact-net/tree/feature/rust-interop

pact544
2021-05-26 14:14
I'm hoping I don't need to specify the Host/Connection headers. I'm sure the Ruby version didn't require that

pact544
2021-05-26 14:27
So yeah, that kinda exposes a pretty brutal experience when using the Rust backend from xUnit - it doesn't capture stdout or anything so you've got absolutely no idea what the backend is doing. My interaction says it's unexpected (which is likely a bug in my new interop code) but you can't tell what interactions it _thinks_ are registered so that you can spot which bit went wrong. You don't get any logging from the Rust backend at all and you can inspect the internals of it in the debugger or anything.

tjones
2021-05-26 15:27
Ah. We were discussing this with the JS implementation - when we use the FFI bindings there, we get the standard out (which is nice), but we don?t have the ability to say ?hey, can you log to this file? (which would be great, and is what the Ruby impl lets you do)

tjones
2021-05-26 15:28
I think we may want to look at extending the Rust side to be more configurable with logging

tjones
2021-05-26 15:30
Also, hi! It?s really great to see so much progress on the .NET engine!

pact544
2021-05-26 21:12
I've extended the Rust FFI locally for my testing with log4rs so maybe I could contribute that back also if it turns out to be useful

pact544
2021-05-26 21:13
I raised it as an issue against pact-reference anyway in case someone there has a better idea

matt.fellows
2021-05-26 23:35
I?d do the same. compressed, they?re probably not that big that it makes a big deal for people these days

pact544
2021-05-27 09:17
Hmmm, so yeah I think I may have hit a bit of a wall on this. Without the logging it's really difficult to know what's going wrong, and the way that you typically do these calls from .Net doesn't really suit how the Rust library is laid out. In C# you do this: ```//Arrange const string eventType = "DetailsView"; this.interactions .UponReceiving($"a request to retrieve events with type '{eventType}'") .Given($"there is one event with type '{eventType}'") .WithRequest(HttpMethod.Get, "/events") .WithQuery("type", eventType) .WithHeader("Accept", "application/json") .WithHeader("Authorization", $"Bearer {Token}") .WillRespond() .WithStatus(200) .WithHeader("Content-Type", "application/json; charset=utf-8") .WithJsonBody(new[] { new { eventType } }); //Act var result = await this.authorisedClient.GetEventsByType(eventType); //Assert result.Should().OnlyContain(e => e.EventType == eventType); this.interactions.Verify();```

pact544
2021-05-27 09:18
The problem is that the `Verify` call will probably never happen in the failure situation because the client call will typically throw an exception and the test will fail early. That means you don't get the output of `mock_server_mismatches` from the Rust side to see what went wrong, and without the stdout/stderr output you can't even go and investigate it.

pact544
2021-05-27 09:19
You could wrap it in a `try/finally` so that `Verify` is always called and then you get the mismatches output, but that's putting a lot on the caller to make sure they always do that. I don't think that's the way to go

pact544
2021-05-27 09:23
Also the entire process crashes when I try to use the `free_string` method to deallocate the string result from `mock_server_mistmatches` so that's also a problem :smile: I think I need to make the P/Invoke interop return an `IntPtr` instead and use `Marshall.PtrToString` to get the string out, then pass the same pointer back to free it

pact544
2021-05-27 09:27
And also if `mock_server_mismatches` returns some errors, how come `mock_server_matched` returns true?

matt.fellows
2021-05-27 10:01
that sounds like a bug

matt.fellows
2021-05-27 10:01
If you can raise an issue, I/@uglyog can look into that

uglyog
2021-05-27 10:01
has joined #pact-net-development

matt.fellows
2021-05-27 10:03
I still think the framework should be responsible for extra checks, rather than relying on the caller. i.e. `Verify()` should be called by Pact .NET, not relied upon by the user

matt.fellows
2021-05-27 10:04
Interesting. I think I do call `free_string` and haven?t seen this. I?ll double check next time I?m there

matt.fellows
2021-05-27 10:04
TBH it?s probably not critical it get called anyway, because the test process is pretty short lived and any memory will be freed at the end of the test process

matt.fellows
2021-05-27 10:04
but still, nice to be correct :wink:

pact544
2021-05-27 10:13
I've managed to get the string to deallocate safely now (it does need to be IntPtr to safely deallocate) but now it crashes on cleanup_mock_server instead :joy: Perhaps I shouldn't even be trying to free this string at all


pact544
2021-05-27 10:27
Yep, that's the issue. I think that's a bit of a wrinkle in the Rust FFI tbh - most of the methods that return strings say you need to free them afterwards with `free_string` but the `mock_server_mismatches` method _doesn't_ need the result to be passed to `free_string`. If you do pass it to `free_string` then the process crashes when you later call `cleanup_mock_server`, presumably because it tries to double-free the mismatches.

pact544
2021-05-27 13:57
So yeah, I'm pretty stuck now tbh. I've added file logging to `mock_server_ffi` and I can get logging out of all the mock server bits, but the matcher modules don't log anything (presumably they use a different log than the global one and/or override the log somewhere internally?). None of my requests will match against registered interactions - I can see the interactions being set up properly and the request coming in looks identical to me. Without seeing the output of the matcher module I totally can't work out why this won't match my requests. Log output: ```2021-05-27 14:45:49 INFO - Successfully initialised logger 2021-05-27 14:45:49 DEBUG - Created new pact between consumer Event API Consumer and provider Event API with ID 1 2021-05-27 14:45:49 DEBUG - Set specification version on pact 1: V2 2021-05-27 14:45:49 TRACE - registering event source with poller: token=Token(0), interests=READABLE | WRITABLE 2021-05-27 14:45:49 DEBUG - Started mock server on 127.0.0.1:6868 2021-05-27 14:45:49 DEBUG - Added new interaction with ID 1 to pact 1 : a request to retrieve event with id '83f9262f-28f1-4703-ab1a-8cfd9e8249c9' 2021-05-27 14:45:49 DEBUG - Updated description for interaction 1: a request to retrieve event with id '83f9262f-28f1-4703-ab1a-8cfd9e8249c9' 2021-05-27 14:45:49 DEBUG - Added provider state for interaction 1: there is an event with id '83f9262f-28f1-4703-ab1a-8cfd9e8249c9' 2021-05-27 14:45:49 DEBUG - Added request to interaction 1: GET /events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9 2021-05-27 14:45:49 DEBUG - Added request header to interaction 1: accept application/json 2021-05-27 14:45:49 DEBUG - Added request header to interaction 1: authorization Bearer abcdef1234567890 2021-05-27 14:45:49 DEBUG - Added response status to interaction 1: 200 2021-05-27 14:45:49 DEBUG - Added response header to interaction 1: content-type application/json; charset=utf-8 2021-05-27 14:45:50 DEBUG - Added response body to interaction 1: Present(606 bytes) 2021-05-27 14:45:53 TRACE - registering event source with poller: token=Token(1), interests=READABLE | WRITABLE 2021-05-27 14:45:53 DEBUG - Creating pact request from hyper request 2021-05-27 14:45:53 DEBUG - Extracting query from uri /events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9 2021-05-27 14:45:53 TRACE - path_and_query -> /events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9 2021-05-27 14:45:53 INFO - Received request Request ( method: GET, path: /events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9, query: None, headers: Some({"accept": ["application/json"], "host": ["localhost:6868"], "connection": ["Keep-Alive"], "authorization": ["Bearer abcdef1234567890"]}), body: Empty ) 2021-05-27 14:45:53 DEBUG - Request did not match: Request was not expected - Request ( method: GET, path: /events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9, query: None, headers: Some({"accept": ["application/json"], "host": ["localhost:6868"], "connection": ["Keep-Alive"], "authorization": ["Bearer abcdef1234567890"]}), body: Empty ) 2021-05-27 14:45:53 WARN - Mismatch: {"method":"GET","path":"/events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9","request":{"body":"","headers":{"accept":"application/json","authorization":"Bearer abcdef1234567890","connection":"Keep-Alive","host":"localhost:6868"},"method":"GET","path":"/events/83f9262f-28f1-4703-ab1a-8cfd9e8249c9"},"type":"request-not-found"} 2021-05-27 14:45:53 INFO - Writing pact out to '../../../pacts/Event API Consumer-Event API.json' 2021-05-27 14:45:53 DEBUG - Writing new pact file to "../../../pacts/Event API Consumer-Event API.json" 2021-05-27 14:45:53 DEBUG - Shutting down mock server with port 6868 2021-05-27 14:45:53 DEBUG - Shutting down mock server with port 6868 - MockServerMetrics { requests: 1 } 2021-05-27 14:45:53 DEBUG - Mock server a681ad3a-2695-4577-aea7-b56cd5e8f462 shutdown - MockServerMetrics { requests: 1 }``` AFAIK it's supposed to ignore the `connection` and `host` headers, and the headers are supposed to be case-insensitive (I've tried both types) and no luck. Second problem: The Ruby implementation has a "clear interactions" method which you call after each unit test. Without this, whenever one interaction fails then every subsequent test fails because the previously-failed interaction still shows up as a mismatched interaction until the entire test run ends. The Rust version doesn't seem to support that.

pact544
2021-05-27 15:07
OK I've managed to add some logging that's worked out there are no interactions inside that Pact, which is why nothing is matching (and presumably why there's no logging from the matching module - there's nothing to actually match against so it'll never get called)

matt.fellows
2021-05-28 00:12
Strange, I?ve not had this problem, but also I have been working with a local copy of the FFI bindings because the new matchers only got merged yesterday

matt.fellows
2021-05-28 00:12
Are you working with the released artifacts or locally compiled ones?

matt.fellows
2021-05-28 00:12
Should we maybe setup a call early next week to pair througch a bit of this? You?ve got the energy, so it makes sense to capitalise on that

pact544
2021-05-28 07:19
So if I've read this code correctly - do you need to set up your interactions before you can start the mock server? `MockServer::new` calls `Pact::thread_safe()` : https://github.com/pact-foundation/pact-reference/blob/2b581d177ec6975bf1d2d94a9fa81f0b19792fb8/rust/pact_mock_server/src/mock_server.rs#L96-L107 And `Pact::thread_safe` creates a clone of the pact wrapped in an Arc/Mutex: https://github.com/pact-foundation/pact-reference/blob/2b581d177ec6975bf1d2d94a9fa81f0b19792fb8/rust/pact_matching/src/models/mod.rs#L925-L927 Doesn't that mean the server is hosting whatever the pact happened to look like at the point the server was started? If so, if you haven't established your interactions yet then the clone will have none, which would match with what I'm seeing.

uglyog
2021-05-28 07:24
Yes, previous version was a separate process so it had to startup at the beginning of the test run, and was a stateful mock server. Each test had to then communicate with it via HTTP.

uglyog
2021-05-28 07:25
The Rust version is in-process, so we start up a new mock server for each test with the Pact required for that test.

uglyog
2021-05-28 07:26
There is not need to communicate with it via HTTP, we just pass it everything directly via FFI call.

uglyog
2021-05-28 07:27
It is way more efficient, but you need to setup the expected interactions first, and then start the server.

pact544
2021-05-28 07:37
Ah, oh dear. Yeah that's not gonna match how PactNet works at all

pact544
2021-05-28 07:38
There's quite a foot gun there as well - it looks like it should work given how the old version works but actually it's silently falling. You're adding interactions to an old clone of a pact that nothing is using, and nothing warns you of that

pact544
2021-05-28 07:40
The current versions of pact libraries have you set up and verify each interaction in a separate unit test, with the server started once at the beginning then the pact file written at the end. You can't support a "unit test per interaction" workflow if you've got to set up all your interactions ahead of time and then verify them all together at the end.

uglyog
2021-05-28 07:45
No, each interaction can be for a separate test. They get merged into the pact file.

uglyog
2021-05-28 07:45
So each test can setup the interaction for that test

pact544
2021-05-28 07:48
But how if you can't start the server yet? The server needs to start at the beginning of the test run, but then you can't add any further interactions into it

pact544
2021-05-28 07:49
This is the current way that PactNet works: https://github.com/pact-foundation/pact-net/blob/master/Samples/EventApi/Consumer.Tests/EventsApiConsumerTests.cs#L24-L57 ? The server starts once at the beginning ? Each test establishes an interaction ? You do the real HTTP call ? You verify the results of the HTTP call

pact544
2021-05-28 07:50
So you need to the verify inside each test, otherwise they won't fail when things go wrong

pact544
2021-05-28 07:51
And you need to do the HTTP call inside each test, so the server has to be started at that point, which means all interactions must already be registered, and therefore the test can't establish the interaction

pact544
2021-05-28 07:52
No wonder I've spent a couple of days struggling to understand why it doesn't work :smile: Those interactions that it looks like I'm adding are actually having no effect because they're being added to a pact that's not being used by the mock server

uglyog
2021-05-28 07:53
I would do something like (excuse my http://non-.Net code): ``` _mockProviderService.Given("there are events with ids '45D80D13-D5A2-48D7-8353-CBB4C0EAABF5', '83F9262F-28F1-4703-AB1A-8CFD9E8249C9' and '3E83A96B-2A0C-49B1-9959-26DF23F83AEB'") .UponReceiving("a request to retrieve all events with no authorization") .With(new ProviderServiceRequest { Method = HttpVerb.Get, Path = "/events", Headers = new Dictionary<string, object> { { "Accept", "application/json" }, } }) .WillRespondWith(new ProviderServiceResponse { Status = 401, Headers = new Dictionary<string, object> { { "Content-Type", "application/json; charset=utf-8" } }, Body = new { message = "Authorization has been denied for this request." } }); _mockProviderService.RunTest { mock_server -> var consumer = new EventsApiClient(mock_server.url()); //Act //Assert await Assert.ThrowsAnyAsync<Exception>(() => consumer.GetAllEvents()); } ```

pact544
2021-05-28 07:54
Yeah you can't do that. That test will always pass no matter what

uglyog
2021-05-28 07:54
The `runTest` method can call start and the beginning and then verify at the end

pact544
2021-05-28 07:55
Plus it's a definitely not an idiomatic way to write C#, and very different to how it is now.

pact544
2021-05-28 07:57
The only way I can see that working is if we start and stop the mock server for each every unit test, but that means it'll be starting and stopping potentially hundreds of times in a given test run, and writing the pact file hundreds of times also. You could only support the merge strategy for the pact file, never overwrite, which would be problematic also. I imagine starting and stopping on the same port over and over will eventually cause problems as well, like the OS just won't accept that happening loads of times or something.

uglyog
2021-05-28 07:58
It does do that. I've implemented that pattern in Pact-JVM and Rust. It is very fast to spin up a server and shut it down again

pact544
2021-05-28 07:59
How do you support overwrite for the pact instead of merge?

uglyog
2021-05-28 07:59
Each mock server gets it's own port

uglyog
2021-05-28 07:59
overwrite won't be work

pact544
2021-05-28 08:00
Oof. Yeah I'm really not sure this is the best approach

uglyog
2021-05-28 08:00
@matt.fellows wants to have a chat next week, but it works in Rust, Java/Jvm and JS, so I'm pretty sure it will work in .Net

pact544
2021-05-28 08:01
@matt.fellows How do the JS and Go versions work? Do they start and stop the server for each interaction as well?

matt.fellows
2021-05-28 08:02
Yep

matt.fellows
2021-05-28 08:02
(sorry just making dinner but will try and follow up later)

matt.fellows
2021-05-28 08:02
The trick is to clear out the pact file before use

pact544
2021-05-28 08:02
You can probably get it to work in .Net yes, but you'll end up with quite a non-idiomatic API and you'll only be able to support merge instead of overwrite (which is really annoying when working locally)

matt.fellows
2021-05-28 08:03
The benefit is that you can do this in parallel

pact544
2021-05-28 08:04
Well, I'll give it a go and see where we end up. Got to say I'm sceptical though :smile: We'll need to drop remote server support as well, and that feature was literally just added

pact544
2021-05-28 08:05
And, some feedback for the Rust FFI end - if the server has already started then you should probably get an error back if you try to add/modify interactions. At the moment it accepts them but actually they have no effect, which has really confused me for 2 days now

uglyog
2021-05-28 08:07
Can you raise an issue for that, otherwise I might forget

pact544
2021-05-28 08:08
Yep, will do

pact544
2021-05-28 08:08
How do you prevent the pact file from becoming corrupted if you start multiple servers all sharing that one file and run the tests in parallel?

pact544
2021-05-28 08:09
You could end up with 2 tests trying to both write the file at the same time

uglyog
2021-05-28 08:09
There is a memory lock as well as a file lock

uglyog
2021-05-28 08:10
Memory lock ensures thread access, file lock for multiple processes

pact544
2021-05-28 08:15
OK so multiple servers accessing the same file are sequential anyway? Is that for the entire time the file is being accessed? Otherwise if you lock on read, release the lock, do the processing, lock again then write, you'd have a race condition where an interaction could get dropped from the file

uglyog
2021-05-28 08:18
The memory lock is for the whole `write_pact` method, the file lock is for the entire read -> merge -> write, but only if the file all ready exists

uglyog
2021-05-28 08:20
There is a potential race condition there, but only for multiple processes accessing the file

pact544
2021-05-28 09:31
OK so the API you naturally end up with if it's "interaction per test" but also "start/stop server for every test" is this. I think that's kinda OK tbh. One problem is if the user has all the tests run in parallel and specifies the same port in multiple tests (instead of omitting the port and letting the backend allocate one dynamically)

matt.fellows
2021-05-28 11:25
I think it?s worth calling out that the new .NET API does not have to look the same as the old. That might be ideal in terms of migration, and I?m not saying we should change it, but if we?re going to revisit what it looks like, now is the time.

matt.fellows
2021-05-28 11:27
There are several classes of errors / problems this new design addresses. I?m not saying it couldn?t be improved, but it certainly solves a bunch of problems we frequently see as maintainers

matt.fellows
2021-05-28 11:31
That looks pretty good to me! I?m assuming there was something like `using` that could be done here - happily it exists.

matt.fellows
2021-05-28 11:32
I almost removed the ability to choose a port, but if I did, I knew that somebody would immediately ask. But we want to discourage it for that exact reason

matt.fellows
2021-05-28 11:33
I?ll have a think about how to do that remotely.

matt.fellows
2021-05-28 11:34
If you do want to catch up, let?s see if we can find an overlapping time. We?re exactly 9 hours ahead of you, so I?m assuming you?re based in UK/EU. We could do 5-6pm or something one weeknight (or later, but after 9pm here is usually once we have the gremlins down for sleep)

matt.fellows
2021-05-28 11:35
Mon, Tues and Thurs are looking :ok_hand: at the moment

pact544
2021-05-28 13:55
OK, I've got it working! :tada:

pact544
2021-05-28 13:55
For simple consumer tests (as in ones with fixed bodies, not ones containing matching rules) then it works absolutely fine and writes out the pact file etc. Bodies containing matchers don't work, but I think we were expecting that at the moment?

pact544
2021-05-28 13:57
I'll have to have a look how you guys do the matching rules stuff in JS/Go and then try and get that working as well

pact544
2021-05-28 13:59
One potentially breaking change I've noticed in the Rust backend btw - the pact file that's written out now doesn't have the same name. In the Ruby version my file would be called `my_consumer-my_provider.json` but in the Rust version that would be `My Consumer-My Provider.json` which has spaces instead of underscores and hasn't been forced to lowercase. I could maybe see that causing problems (especially the spaces).

pact544
2021-05-28 20:19
And now the matchers are fixed as well since I've got a spare moment this evening, and all the consumer tests in the sample now work :tada: They really are quite slow though. I imagine starting and stopping the server over and over is quite a bottleneck. I can try out the current stable version for comparison but I don't remember them being this slow.

pact544
2021-05-28 20:36
Struggling to get the verification to work though. My code constructs the args properly but when it calls in to the `verify` method it gets a status code of 4 (invalid arguments). If I pass these exact same argument into the `pact_verifier_cli.exe` though then they work absolutely fine. Since I can't get the stderr logging I have no idea which of those it doesn't like.

pact544
2021-05-28 20:39
I wonder if those file path separators need double-escaping

matt.fellows
2021-05-28 22:26
The FFI takes newline delimited arguments

matt.fellows
2021-05-28 22:26
That's unbelievably slow.

matt.fellows
2021-05-28 22:27
My node JS tests run in in fractions of a second

matt.fellows
2021-05-28 23:28
It looks ok to my eyes though. We'll get the logging so it can goto file and stdout (configurable)

matt.fellows
2021-05-28 23:39
Matchers on bodies should definitely work.

matt.fellows
2021-05-28 23:39
I added support for the other parts recently also

matt.fellows
2021-05-28 23:39
But that may not be released it only just got merged

matt.fellows
2021-05-28 23:40
The file name shouldn't be relevant for functionality but probably good to clean that up as you say

matt.fellows
2021-05-28 23:41
It's the content that matters

pact544
2021-05-29 08:14
I've had a bit of a thought on that as well. Logging to a file would be great, but what would be even better is if you could init with a string as a sink (I've not checked it there are any crates for that or a way to redirect stdout though). A file is a good first step, but in reality the UX would be annoying. Your test would fall and it could only say "go and check the file to find out why", and the file would have output from every test. If it could log to a string sink instead (per server port, like with mismatches) then the test could retrieve it and include it in the test output. That would be a really good UX.

matt.fellows
2021-05-29 08:15
Yep that's a good idea

matt.fellows
2021-05-29 08:15
Or if it just returned the log at the end (like fetching the mismatches)

matt.fellows
2021-05-29 08:16
Writing to the same address might be problematic, but providing an option to fetch the current log might be simpler and safer. What do you think?

pact544
2021-05-29 08:16
Yeah that'd be best. I can include that in the xUnit output then, so everything you need to know for your failing test should just be there

pact544
2021-05-29 08:17
Perhaps we should've gone the route of just calling the CLI like the ruby one did after all :joy:

matt.fellows
2021-05-29 08:24
Just so I'm clear - we talking consumer or provider side for the logging? Might get some time for a play later (dinner Joe :wave:)

uglyog
2021-05-30 00:08
That's a really good idea. I'll try implement it today

matt.fellows
2021-05-30 00:27
That's be awesome, thanks

matt.fellows
2021-05-30 02:26
As an FYI, this is an example consumer test (just one) that goes through the full cycle. It?s not passing through a test framework like Jest/Mocha but I think is still indicative of the performance

matt.fellows
2021-05-30 02:27
And my machine is far from quick!

greg595au
2021-05-30 05:57
Hi matt and co - sorry I have been offline this weekend.. my mac (replacing the existing machine) is almost ready - just emails and get the project from git to go

uglyog
2021-05-30 06:32
@pact544 @matt.fellows I've been playing around with this. While I've got the logs being captured into a buffer, we can't stop the logs being interleaved from different threads.

uglyog
2021-05-30 06:32
The problem is that the matching code runs on a thread pool, so it could be running on any number of threads.

uglyog
2021-05-30 06:35
The only way it might work, is having a thread pool per mock server, but that would be wasting thread resources

matt.fellows
2021-05-30 07:43
Ah makes sense.

matt.fellows
2021-05-30 07:45
How expensive are we talking? Could we reduce the number of threads per server?

uglyog
2021-05-30 07:47
It's actually a little more complex. It is currently configured for one thread in the pool, but it is async on a Tokio runtime, so we can't use thread local state because different parts of different mock servers might be scheduled at any given time.

pact544
2021-05-30 07:48
I'd seen it as a property on the mock server object, which you know at the point you run the consumer tests so you can pass a mutable reference to its log buffer around. Probably be a bit awkward passing it around instead of holding it somewhere centrally though

uglyog
2021-05-30 07:49
The problem is the logging infrastructure is global, so you can't know which mock server the log entry is for

matt.fellows
2021-05-30 07:49
Yeah, I assume that's the change that needs to happen

matt.fellows
2021-05-30 07:50
(if we go that route)

pact544
2021-05-30 07:51
Is the verifier side any easier or is that also on multiple threads? At the moment there's no way to get anything other than a generic failed error code, so it's even more needed there

matt.fellows
2021-05-30 07:53
You're probably unlikely to be running other pact tests, although I suppose you could be both a consumer and provider

pact544
2021-05-30 07:54
Or perhaps we store the failures as actual objects and return those instead of a string representation of everything? Then multi threaded isn't a problem and it's not via global infrastructure

matt.fellows
2021-05-30 07:54
Are you saying the the xunit framework doesn't let you see the stdout at all?it just swallows it and discards it

pact544
2021-05-30 07:55
Essentially, yes

matt.fellows
2021-05-30 07:55
Crazy

matt.fellows
2021-05-30 07:55
I'd like a JSON representation of the errors though

matt.fellows
2021-05-30 07:56
That is something on my list of things to investigate (ala what the mock server does but in reverse)

pact544
2021-05-30 07:57
Yeah I think that's fine. For consumer tests it already stores the mismatches I think, and just converts to JSON as part of the FFI? We could do the same for verification errors.

matt.fellows
2021-05-30 07:58
What's nice about structured data is you can convert them back into tests results (so you get a set of green ticks/crosses on provider side too)

pact544
2021-05-30 07:59
Yeah that'd be cool. Not sure how that'd work on the .Net side but I could see that for JS


uglyog
2021-05-30 08:03
Might be able to push the mock server ID onto that, and then accumulate the log entries by that value

matt.fellows
2021-05-30 08:03
:raised_hands:

matt.fellows
2021-05-30 08:04
Most frameworks have hooks to be able to generate tests. I actually haven't done it for JS because too many frameworks to do it for. But Go was easy because just one

matt.fellows
2021-05-30 08:05
More generally though, structured data I think gives flexibility

matt.fellows
2021-05-30 08:05
E.g. a simple/quick wrapper could just use the default Rust output, complex integrations could do as they please

pact544
2021-05-30 19:18
I fixed this btw :thumbsup: I was passing an arg like `--loglevel info<newline>--foo bar` instead of having a newline between an argument and its value. Now that everything is separated by newline it's passing in fine, but I get a general verification failure and no logging so can't tell why.

pact544
2021-05-30 20:20
I've added the following to `pact_provider_ffi/lib.rs` by the way to get some file logging out: ```/// Init the library with logging directed to a file as well as stdout /// /// # Safety /// /// Exported functions are inherently unsafe. /// /// # Errors /// /// Errors are returned as non-zero numeric values. /// /// | Error | Description | /// |-------|-------------| /// | -1 | Unable to convert the file name to a valid string | /// | -2 | Unable to create a logging sink with the given file name | /// | -3 | Unable to initialise the logger | /// | -4 | A null pointer was received | #[no_mangle] pub unsafe extern "C" fn init_with_file( file_name: *const c_char, level_filter: LevelFilter, ) -> i32 { if file_name.is_null() { return -4; } let file_name = match CStr::from_ptr(file_name).to_str() { Ok(file_name) => file_name, Err(_) => return -1 }; let file = match fern::log_file(file_name) { Ok(f) => f, Err(_) => return -2 }; let result = fern::Dispatch::new() .format(|out, message, record| { out.finish(format_args!( "[{}][{}] {}", record.target(), record.level(), message )) }) .level(level_filter) .chain(std::io::stdout()) .chain(file) .apply(); match result { Ok(()) => 0, Err(_) => -3 } }``` It uses `fern` since `pact_matching_ffi` already uses that, except that sets up a thread local logger instead of a global one, which isn't what you need when doing verification via FFI really.

pact544
2021-05-30 20:21
As an aside, is there any particular reason the Rust code doesn't use the standard `rustfmt` and `clippy` conventions? Whenever I'm doing Rust code I always get in the habit of doing a `cargo fmt` before committing anything (you could set it up as a pre-commit hook even) and making sure I've sorted all clippy warnings out

matt.fellows
2021-05-31 00:20
Ron added the interfaces from the matching ffi lib, so I think that would be redundant now

uglyog
2021-05-31 04:50
Task local vars is working! :tada:

uglyog
2021-05-31 04:51
```$ src/consumer-verification basic ../../rust/target/debug/libpact_mock_server_ffi.so This is consumer-verification 0.0.0. Setup logging result: 0 Running basic pact test Mock server started on port 46267 Executing request against http://localhost:46267/mallory?name=ron&status=good * Trying 127.0.0.1:46267... * Connected to localhost (127.0.0.1) port 46267 (#0) > GET /mallory?name=ron&status=good HTTP/1.1 Host: localhost:46267 Accept: */* * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < access-control-allow-origin: * < access-control-allow-headers: * < access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH < access-control-expose-headers: Location, Link < content-type: text/html < content-length: 28 < date: Mon, 31 May 2021 04:49:08 GMT < * Connection #0 to host localhost left intact "That is some good Mallory." OK: Mock server verified all requests, as expected --------------- MOCK SERVER LOGS --------------- [DEBUG][pact_mock_server::hyper_server] Creating pact request from hyper request [DEBUG][pact_mock_server::hyper_server] Extracting query from uri /mallory?name=ron&status=good [INFO][pact_mock_server::hyper_server] Received request Request ( method: GET, path: /mallory, query: Some({"name": ["ron"], "status": ["good"]}), headers: Some({"accept": ["*/*"], "host": ["localhost:46267"]}), body: Empty ) [INFO][pact_matching] comparing to expected Request ( method: GET, path: /mallory, query: Some({"status": ["good"], "name": ["ron"]}), headers: None, body: Missing ) [DEBUG][pact_matching] body: '' [DEBUG][pact_matching] matching_rules: MatchingRules { rules: {} } [DEBUG][pact_matching] generators: Generators { categories: {} } [DEBUG][pact_matching::matchers] String -> String: comparing '/mallory' to '/mallory' using Equality [DEBUG][pact_matching] expected content type = '*/*', actual content type = '*/*' [DEBUG][pact_matching] content type header matcher = 'None' [DEBUG][pact_matching::matchers] String -> String: comparing 'good' to 'good' using Equality [DEBUG][pact_matching::matchers] String -> String: comparing 'ron' to 'ron' using Equality [DEBUG][pact_matching] --> Mismatches: [] [DEBUG][pact_mock_server::hyper_server] Test context = {"mockServer": Object({"href": String("http://127.0.0.1:46267"), "port": Number(46267)})} [INFO][pact_mock_server::hyper_server] Request matched, sending response Response ( status: 200, headers: Some({"Content-Type": ["text/html"]}), body: Present(28 bytes, text/html) ) [DEBUG][pact_mock_server::hyper_server] body: '"That is some good Mallory."' ------------------------------------------------ ------------------ GLOBAL LOGS ------------------ [WARN][pact_matching::models] No metadata found in pact file "<create_mock_server>", assuming V3 specification [WARN][pact_matching::models] No metadata found in pact file "<create_mock_server>", assuming V3 specification [DEBUG][pact_mock_server::mock_server] Started mock server on 127.0.0.1:46267 [DEBUG][pact_mock_server::server_manager] Shutting down mock server with port 46267 [DEBUG][pact_mock_server::server_manager] Shutting down mock server with port 46267 - MockServerMetrics { requests: 1 } [DEBUG][pact_mock_server::mock_server] Mock server f23a4853-09ad-4ce7-b489-3c7a51a4cba5 shutdown - MockServerMetrics { requests: 1 } ------------------------------------------------```

uglyog
2021-05-31 04:52
Global log entries are not associated with any mock server, and each mock server will be able to fetch it's log entries regardless of threads

uglyog
2021-05-31 04:54
Expect for the thread local support, but we should consolidate that

uglyog
2021-05-31 04:58
Clippy is run as part of the CI build. I'm generally apposed to formatting tools (like lints), as I don't feel they provide any value apart for people who get agitated with formatting mismatches. I prefer the commit diffs to only contain the functional changes. But that is just me.

uglyog
2021-05-31 04:58
@matt.fellows has to deal with me always removing his lint tools and deleting his commit hooks.

uglyog
2021-05-31 05:21
Speaking of which, latest build has failed due to a clippy violation

matt.fellows
2021-05-31 05:44
I don?t like any formatting/linting that requires humans to do anything. But my OCD does like consistent formatting. More importantly (and I could be wrong about Clippy), I want those tools to tell me when I?m doing something stupid, or if I could be doing it better - better I want them to do it for me

matt.fellows
2021-05-31 05:44
I absolutely don?t want to get into dumb arguments about spaces/tabs, the size of the tabs etc.

matt.fellows
2021-05-31 05:45
That?s one thing Go does well - this is the format you use. No exceptions, don?t waste valuable brain capacity on it

matt.fellows
2021-05-31 05:45
wow! Awesome

uglyog
2021-05-31 05:47
I need to verify it working with multiple threads, but is a problem for another day

uglyog
2021-05-31 05:49
Clippy has been pretty good, you can learn to be better at Rust by fixing the warnings

matt.fellows
2021-05-31 05:51
is that something that gives you compile time feedback, or in the IDE? or better question - how should I use it :slightly_smiling_face:

uglyog
2021-05-31 05:51
But the build I just fixed was not a useful one

uglyog
2021-05-31 05:53
It's CLI at the moment, but I'm sure you can set something in the IDE

uglyog
2021-05-31 05:55
There is a VSC plugin, but look like it is slow

matt.fellows
2021-05-31 05:55
> Look like it is slow It?s ok, my rust compiler is also slow

matt.fellows
2021-05-31 05:56
This one? :stuck_out_tongue:

uglyog
2021-05-31 05:57
Yeah, that! :smile:


matt.fellows
2021-05-31 05:59
haha thanks, found that one too

uglyog
2021-05-31 06:02
IntelliJ IDEA supports it as well

matt.fellows
2021-05-31 06:05
It might be time for me to bite that bullet

uglyog
2021-05-31 06:32
Clippy in IntelliJ feels really slow, and that's on my metabox, CLI is better

uglyog
2021-05-31 06:33
You can just run `cargo clippy` on the project

pact544
2021-05-31 07:37
Yeah I like the "just follow the format" and "tool does it for me" approach that `cargo fmt` does for me. I'm really struggling to read the code locally because it's so dense (I have some sight problems) so I've had to reformat to be able to follow it. That does make it difficult to contribute though.

pact544
2021-05-31 07:43
So headline is that both provider and consumer tests now work in my PactNet branch (which is essentially a rewrite pretty much from scratch now tbh) :tada: There's plenty still to do, like adding V3 matchers (easy), integrating with whatever logging solution lands in core, redoing the sample to http://ASP.Net Core (easy) and sorting the unit tests out (tests for native integration might be fun...).

pact544
2021-05-31 07:44
Oh and message pacts, of course! It should be very natural to add those on now given the new API I've created.

greg595au
2021-05-31 08:42
hi all... looks like my mac is set up.. where can i fit into this discussion

matt.fellows
2021-05-31 11:03
You?ll probably have to do more work to actually expose the message pact interface and make it usable - keen to hear your thoughts on this (outside of the proxy approach mentioned/alluded to at https://github.com/pact-foundation/pact-reference/issues/110)

matt.fellows
2021-05-31 11:11
@pact544 first up, thanks - this work was so timely and getting onto the Rust core is a strategic priority for the framework. Let?s step back for a quick moment. There are a few things we should discuss before we go too far, and some flags to raise as we progress (storm!?) into a v3 release: 1. Adam - what are your plans/ambitions going forward? We recently reached out to the community for involvement and have a number of parties interested in driving forward the .NET agenda, so it would be good to know what your plans are and how we can accommodate them / work together 2. For getting the next major Pact .NET out, I suggest we get a project board setup for visibility, discussion, collaboration etc. We should also put it on the main home page that this work is underway (and probably a pinned issue) (https://github.com/pact-foundation/pact-js/projects/3 and https://github.com/pact-foundation/pact-go/projects/2 have them) 3. QA / release process (how do we validate the new interface, FFI boundary, feature tests etc.) 4. As far as getting beta users and feedback, we have a Pactflow POST going out in June - we can do a callout for beta users to get involved, and I?d also like to do a callout to all of our new contributors there 5. Migration guide - we?ll need one of these to help users make the transition 6. Blogs, tutorials .net workshop update - 7. Message support - how do we see that working? :point_down: let?s get a :thread: going on this

greg595au
2021-05-31 11:45
for QA/Release, do we want a slightly more formal methodology? Sets of tests for critical and not critical operations (ie must work every release and have a lower expectation of the non-critical)

greg595au
2021-05-31 11:46
Specs need to be formulated with minimal standards that enable integrations like FFI to be exercised with RFC compliance in mind

greg595au
2021-05-31 11:48
If the new .NET does not have to look like the current one, perhaps a wrapper to enable quick updating would allow quicker uptake of an upgrade, with a migration strategy so users can assess the size and work over a period of time instead of big banging it

greg595au
2021-05-31 11:55
The ultimate goal would be as much automated testing as feasible, with CI/CD quality gates for measured values such as unit test code coverage, pass rates and code smells (eg sonarqube)

pact544
2021-05-31 18:52
In terms of my intentions - my company is very heavily invested in PactNet as pushed by me a number of years ago, and I've been checking in regularly for message-type support. Upon seeing the call for replacement maintainers I asked our Director if I could take a stab at it on work time, so I spent quite a lot of last week almost full time on it (and can spend a lot this coming week also). I'm happy to be a contributor but not sure I can commit to X hours per week or anything like that unless my company allows me to do so on work time. I was kinda planning to discuss that with them in the near future, and I can see a good case for allowing me (and others at my company) to help out. I think the alternative would be that we dropped PactNet entirely and went with a very different approach as it's a risk relying heavily on an open source project with no maintainer, so I can see the talks generally going well.

pact544
2021-05-31 18:57
In terms of migrating users over to a Rust-backed version - I mean, effectively this is a complete rewrite at the moment for 2 key reasons: 1. The semantics of the mock server have changed so much (now it's set up interactions then start it vs. old way of starting then setting up/tearing down interactions as you go) that people are going to have to rewrite their consumer tests pretty much no matter what. I haven't tried it obviously, but I think some kind of compatibility wrapper is probably a non-starter. 2. Some of the existing API for PactNet just wouldn't be compatible with some v3 stuff. There are too many things of type `object` whereas all the Rust backend expects nicely split out strings. For example, query string params are now very different. Unfortunately, I think it looks like a "big bang" from where I'm sitting, albeit a pretty easy transition that should be quite easy to write a migration guide for.

pact544
2021-05-31 19:01
On point 1 above - I'd really urge us to reconsider that approach. I know we said it makes the mock server more efficient, but in my testing it's made performance much worse. Each consumer test now takes ~3s on my very fast machine and you're likely to have dozens of them. I haven't done any profiling to find out why but I'd put good money on it being the mock server starting and stopping over and over for each interaction. It could also be that the FFI is very fine-grained with lots of calls, where FFI is known to be quite slow, but I'd say that's unlikely to be contributing seconds of latency.

pact544
2021-05-31 19:08
On QA - I have absolutely no idea short of beta testing. Obviously you'd have unit/integration tests in there, but writing those for interop code sounds like a real nightmare. You can't inspect the internal state of the other end of the FFI boundary so you'd basically have to write proper consumer tests in order to validate and check the resultant pact file afterwards.

pact544
2021-05-31 19:09
On release process - obviously it would be a breaking change so we bump major version, and we also need to distribute the FFI libs on an OS-specific way. I think you can use NuGet for this to bundle native deps and then it restores the correct one at build time via OS detection, but we'd need to check that

pact544
2021-05-31 19:11
On message support - I've not given too much thought to how you have an equivalent "mock server" given you don't know which message queue the client is using. I was hoping to steal ideas from other Pact libraries for that :smile: The actual API inside PactNet itself is pretty straightforward though I think once the message queue tech is abstracted

pact544
2021-05-31 19:15
Oh, another thing for QA - we're going to have to do plenty of cross-platform testing now that we're entirely reliant on FFI. There are probably tons of gotchas (even stuff like the library having a different name/extension on different platforms)

pact544
2021-06-01 06:38
I had a quick look how `Com-Pact` (an alternative PactNet implementation in pure C#) works for message pacts, and in that you simply supply a `Func<string, object>` which will be called for each consumer/provider interaction which is expected to work like the real message queue. I think that's a good approach and it abstracts away the underlying MQ technology from PactNet.

matt.fellows
2021-06-01 07:02
sounds very similar to the other approaches

matt.fellows
2021-06-01 07:03
FYI see the diagrams here for the Ruby implementation: https://github.com/pact-foundation/pact-message-demo

matt.fellows
2021-06-01 07:03
This is how Pact Go \ JS \ PHP \ Python do it

matt.fellows
2021-06-01 07:04
We talked about passing a function to the FFI to invoke, but the thinking was that may be problematic - e.g. async/promises etc.

matt.fellows
2021-06-01 07:05
so it currently works like the verifier, needing an HTTP endpoint to call. If the framework spins this up, it can simply register those `Func<string, string>`and the framework can map the incoming message (via the `description` ) to the correct registered function

matt.fellows
2021-06-01 07:05
this was what I was alludinsg to with provider states. Basically the same mechanism

yann.courtel
2021-06-01 08:25
Hi @pact544 it actually is. I've done the change on the pact-net side but was stuck because I didn't have the rust system implemented :slightly_smiling_face:

yann.courtel
2021-06-01 08:25
I might take your branch and simply plug my integration test / code to see if it works

yann.courtel
2021-06-01 08:34
Hi evereone. Thanks @pact544 on all the work with the Rust integration! That's going to prove useful! I will be focused on the messaging part but have to really understand the difference with the Rust integration. As far as pact messages go, I'm not 100% sold on the approach with a proxy server that simulates an HTTP request. That would mean for each interaction model we would need to have a specific route... maybe look at the java approach and have a build-in verification for the messages. Regardless, I stand with my 4 hours contribution per week. in the next few weeks.

yann.courtel
2021-06-01 08:36
@pact544 on our internal lib, we created a fixture class that takes care of the port, clearing interactions, the mock service, etc. That could be a way to "factorize" the work you do initializing each test.

pact544
2021-06-01 09:14
Yeah cool. The way I saw it working was adding a method onto `IPactBuilder` that returns an `IMessageBuilder` which mirrors the existing `UponReceiving` which returns an `IRequestBuilder`. That way the API means you can't get it wrong, so like: ```public interface IPactBuilder { IRequestBuilder UponReceiving(string description); IMessageBuilder WhenReceiving(...); // or whatever the method is called }```

yann.courtel
2021-06-01 10:00
The WhenReceiving is not bad. That would allow a new builder to implicitly add the provider state with the description. (on my end, the provider state is mandatory to simulate the message on the provider side) The IMessageBuilder will also need to Verify a certain message is being sent without any problem.

matt.fellows
2021-06-01 10:01
`ExpectsToReceive` would be more consistent with the other languages, FWIW

pact544
2021-06-01 10:05
That's the one :thumbsup: Couldn't remember the term used

yann.courtel
2021-06-01 10:07
@matt.fellows Do you see another interaction model (in the upcoming PACT specs)? We would need to create a builder for each one in that case. Not a bad idea.

matt.fellows
2021-06-01 10:07
> I will be focused on the messaging part but have to really understand the difference with the Rust integration. Awesome - hopefully your work does translate nicely! > As far as pact messages go, I?m not 100% sold on the approach with a proxy server that simulates an HTTP request. I?m not sure I understand. There is no simulation of the HTTP request with message pact, because in message pact it doesn?t model an HTTP req/res cycle. The HTTP proxy is simply an implementation detail for *message producer tests* in order to communicate to the message pact FFI interface, which is essentially a call to a verifier CLI - see https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_verifier_cli#verifying-message-pacts (it needs to communicate to an HTTP interface, something I don?t think we should expose to an end user wanting to test that their function is able to produce the correct message for say, a kafka or SNS topic) > That would mean for each interaction model we would need to have a specific route... maybe look at the java approach and have a build-in verification for the messages. Java does it all in proc, but it is not using the FFI interface. The luxury of Ron being the core maintainer of both JVM and Rust means he?s happy to do that work twice :wink: > Regardless, I stand with my 4 hours contribution per week. in the next few weeks. Amazing - thanks!

pact544
2021-06-01 10:07
Yeah I think it's best doing it that way because then all the 'sub-operations' are grouped together on the specific builder

pact544
2021-06-01 10:08
Like that means you can't accidentally do a `WithQuery` on a message interaction and stuff

yann.courtel
2021-06-01 10:08
Got it @matt.fellows in any way, to me the first step is to have a consumer pact with a message using the rust and the provider side will follow. Thanks for the clarification

yann.courtel
2021-06-01 10:09
and each interaction model is served by the IPactBuilder but work independently. Agreed!

pact544
2021-06-01 10:10
I'd also had a thought about how to handle different spec versions and thought we probably want like an `IPactBuilderV2` and `IPactBuilderV3` to support different things you can do between specs. For example, v3 supports multiple provider states and provider state params, but v2 doesn't. If you put `GivenWithParam` on `IRequestBuilder` then you've got to validate every call to check if the spec supports it. I'd rather the API means you just can't get it wrong

matt.fellows
2021-06-01 10:11
Indeed

matt.fellows
2021-06-01 10:11
I?m really not wedded to implementation, and I?m an outsider as far as .NET is concerned. I have to trust that you know what is ideal for .NET library consumers

matt.fellows
2021-06-01 10:12
I?m mostly here to provide the frameworks overarching goals, help wrangle, coordinate where I see opportunity and connect people

matt.fellows
2021-06-01 10:14
@greg595au?s points around testing are valid, so I would love to encourage us to think about what the testing approach looks like. I think testing the FFI interface directly (from the .NET code base) may not be the best use of time though, and feature level suites that exercise the interface in the ways we need to remain reliable are probably a better approach. This way we prevent breaking API changes at the consumer level, which will help stability, we prevent breaking changes from FFI going out and we also get a nice set of examples we can share with users

matt.fellows
2021-06-01 10:15
We kind of do this in Pact JS. The example projects now get tested as part of the build, so if we change the API in a backwards incompatible way, they will discover it. That was a bit by accident, but going forward we?ll invest in more of those because it turns out they?ve been really handy

matt.fellows
2021-06-01 10:15
yes

matt.fellows
2021-06-01 10:16
to both :stuck_out_tongue:

pact544
2021-06-01 10:16
Yeah I think the PactNet stuff is already like that, with the sample actually containing tests :thumbsup: They just probably need fleshing out a bit more

matt.fellows
2021-06-01 10:16
How are you going to prevent V3 matchers from goinsg into a V2 pact? Presumably you allow essentially any object in the body, which can contain matchers? Can you detect htat at the type layer? (ideal)

matt.fellows
2021-06-01 10:17
I had to resort to reflection in Go, which was a bit shit

pact544
2021-06-01 10:17
It needs a test to actually look what the resultant spec file looks like though as well, which isn't there at the moment. They're samples of how to write consumer tests, but don't actually verify the the resultant pact file is valid or did everything you expected

pact544
2021-06-01 10:17
For example, if `IRequestBuilder.WithQuery` just did nothing, the consumer tests would all pass but the resultant pact file would be wrong. You need tests to make sure it does call the FFI when you call it

matt.fellows
2021-06-01 10:18
I would _love_ to see a feature suite (e.g. in BDD/Cucumber) that specifies the behaviour we?d like to see for _all_ rust implementations

matt.fellows
2021-06-01 10:18
and then implementing that per language is the roadmap to done

matt.fellows
2021-06-01 10:18
@greg595au what do you think about that concept?

pact544
2021-06-01 10:18
Yeah that'd be great, just implementing the steps files per library

matt.fellows
2021-06-01 10:21
> @matt.fellows Do you see another interaction model (in the upcoming PACT specs)? We would need to create a builder for each one in that case. Not a bad idea. yes, v4 introduces a few new things. The main interaction level ones are synchronous messages (1 request <-> * response). There is also plugins coming, but that would probably be a separate interface altogether. See also https://github.com/pact-foundation/pact-specification/tree/version-4/ and https://github.com/pact-foundation/pact-specification/issues/71 It just turned 1, so Ron is about to kill it and close it off.

matt.fellows
2021-06-01 10:22
The rest of it is going to be new matchers, and new annotations for the Pact file (labels, pending tests). HTTP interactions can also be in the same file as the Messages

pact544
2021-06-01 10:25
I've done a lot of BDD in .Net but for anyone that hasn't: https://docs.specflow.org/projects/getting-started/en/latest/index.html

pact544
2021-06-01 10:26
That's basically the only BDD framework, but it's also very good and integrates with VS very nicely

matt.fellows
2021-06-01 10:26
I?ve not done .NET before, but even I?ve heard of it!

pact544
2021-06-01 10:28
Yeah adding v3 matchers to v2 pacts is def problematic because at the moment the request body is just a `dynamic` (and has to be really) which the Rust end translates into the proper rules (which is a very nice feature btw)

matt.fellows
2021-06-01 10:28
I was hoping you had some brilliant idea I could steal for Pact Go, but that makes me feel better

matt.fellows
2021-06-01 10:29
So what I have, is a method that navigates the object that was put in, and errors if it contains a matcher with the wrong specification version

matt.fellows
2021-06-01 10:29
But that might be better off in the rust core, tbh

pact544
2021-06-01 10:29
Com-Pact does it a very different way where you build up the request very rigidly, which I do kinda like but it's also very strict and verbose, like this: ``` .With(Pact.JsonContent.With( Some.String.Named("eventId").LikeGuid("f84fe18f-d871-4dad-9723-65b6dc9b0578"), Some.Object.Named("recipe").With( Some.Element.Named("name").Like("A Recipe"), Some.Element.Named("instructions").Like("Mix it up"), Some.Array.Named("ingredients").InWhichEveryElementIs(ingredient) )))```


matt.fellows
2021-06-01 10:31
I considered that, but I know how JS and Go get used based on a few years of maintainership, and I didn?t think it would fly (despite have a much stronger type system)

matt.fellows
2021-06-01 10:31
trade offs

pact544
2021-06-01 10:33
Yeah you could do the same in .Net and have like an `IBodyBuilderV2` and `IBodyBuilderV3` with lots of methods for building up the body that were only valid for the specific spec version, but I don't think that would fly with users either. It's very verbose even if it is technically the most correct way

pact544
2021-06-01 10:34
Like ```.WithJsonBody(builder => builder.Object.Like(...))``` and chain those all the way down like Com-Pact does

yann.courtel
2021-06-01 15:20
Hey @matt.fellows we are doing BDD also heavily with Specflow. Our PACT lib actually has some BDD integrated. We could add some for sure. Sharing the Gerkins would be an idea.

pact544
2021-06-01 16:02
I've started filling in unit tests for my branch now, with all the interop stuff abstracted so at least I can prove that everything _should_ call the Rust core properly as long as that one interop class is implemented properly, although obviously that one interop class currently has no tests because they'd be very tricky to write properly. We should definitely do at least one happy path integration test against it though just to make sure.

pact544
2021-06-01 16:42
OK, integration test is there also which fully starts the mock server with a properly setup pact and interaction, calls the mock server, writes the file and verifies the pact contents afterwards, all using the real Rust core library :thumbsup:

matt.fellows
2021-06-01 22:21
That would be ace


greg595au
2021-06-02 01:45
@matt.fellows we can write cucumber style tests in a tech agnostic way. This gives us a lot of flexibility and re-use. @pact544 interested to see what u have in that space. We'll need to agree on the statements but i think we can do that in a few conference sessions

pact544
2021-06-02 06:40
Yeah I was thinking along the lines of ```Feature: Multiple provider states Scenario: v2 pact should error Given a v2 pact between 'consumer' and 'provider' And an interaction named 'v2 multi provider states' When I add the provider state 'test provider state' And I add the provider state 'another provider state' Then I should receive the error 'v2 pacts don't support multiple provider states' Scenario: v3 pact should work Given a v3 pact between 'consumer' and 'provider' And an interaction named 'v3 multi provider states' When I add the provider state 'test provider state' And I add the provider state 'another provider state' Then the interaction should have provider state 'test provider state' And the interaction should have provider state 'another provider state'``` If those were all in a centralised place as the spec files, then each library could simply implement the steps files required to drive it all and we'd have a kind of 'spec compliance' suite which is library-agnostic. That'd be awesome. We'd just have to be careful that the tests themselves weren't written with particular implementations in mind or something because the idiomatic APIs across different languages may make it difficult to fit in with the steps otherwise.

matt.fellows
2021-06-02 06:48
exactly

matt.fellows
2021-06-02 06:49
As an aside, Seb Rose is a big Pact fan - I wonder if we could get him involved in some way?

matt.fellows
2021-06-02 06:49
He also recently got Beth to talk about Pact at an upcoming conference, so perhaps we could ask him to return the favour :stuck_out_tongue:

yann.courtel
2021-06-02 08:55
It's not a bad idea to put the specs as Gerkins based but just a footnote, with specflow, it is quite different from normal integration tests. While it's a good idea, I think we should do it at the end because it can be quite a big code base.

pact544
2021-06-02 08:58
Yeah at the moment I've just got some basic integration tests at both the FFI level and the the 'user API' level to validate that everything works correctly, but they definitely won't be as extensive as the kind of thing I've outlined there. Just simple happy path stuff

yann.courtel
2021-06-02 09:03
One thing they do in pact js I think is to separate the matchers based on specs. We could imagine another way of defining the matching rules for v3 but yeah the problem would be the validation between configuring a v2 pact with v3 matchers...

pact544
2021-06-02 10:12
I've just pushed the change that enables this :thumbsup: So now you specify the version at the point you create the Pact object, and you get a versioned builder back which only lets you do things that are valid for that version: https://github.com/adamrodger/pact-net/blob/feature/rust-interop/tests/PactNet.Native.Tests/PactExtensionsTests.cs#L68-L97

greg595au
2021-06-02 10:46
hi @pact544 your cukes is looking good. I concur with a central repo of tests as we ensure the product will have been consistent coverage from a "font of knowledge"

greg595au
2021-06-02 10:47
@pact544 Have you ever tried the @ tags? Names are good too, tags enalbe us to control/filter the test suites

pact544
2021-06-02 12:23
Yeah for sure :thumbsup:

pact544
2021-06-02 15:27
Tests in for the verifier as well now, with the sample provider test acting as the integration test at the moment.

pact544
2021-06-02 15:28
I _think_ we're almost at v3 support for request/response now (not messages though obviously, waiting to see what @yann.courtel comes up with). I've added the extra matchers, just need to add the extra v3 request stuff like provider states with params and binary message bodies. Those are all really easy though.

yann.courtel
2021-06-03 07:12
Hey Adam, I think, as I said, that if they tests are good to go and we are compatible with the spec 2.0, we should go ahead and make a pull review first because putting the messages support. What do you think @matt.fellows Just so that we don't put to many things at once. What do you think guys?

pact544
2021-06-03 07:14
Yeah it should have v2 support afaik. I think the only thing missing from v3 support is binary message bodies now. Just going through the spec and making sure

pact544
2021-06-03 07:20
So yeah, missing for full v3 support: ? Matchers for (all very easy): ? Equality ? Null ? Include ? Combining matchers with OR (need to check how the Rust core wants these formatted) ? Generators (propose we don't make that a base req) I can do all of that today no probs. Binary bodies are actually v4 so I don't need to do those after all.

yann.courtel
2021-06-03 07:21
ok sounds good! I will just focus on adding provider states by the API tests for now. The messages will come right after. Shall I push onto your branch directly?

pact544
2021-06-03 07:23
I suppose it's one for @matt.fellows. You can def raise a PR against my fork, but then it's weird that the dev is happening in my fork instead of the main repo :slightly_smiling_face: But then also I don't have push access to the main repo so I guess it has to be there?

yann.courtel
2021-06-03 07:24
Well why not, it's like an intermediary branch :wink: I tried without the Rust support and I have too many things to duplicate unfortunately

matt.fellows
2021-06-03 07:28
All for getting it out and in the hands of people sooner rather than later

matt.fellows
2021-06-03 07:28
those matchers are advanced uses, and are not commonly used across the ecosystem yet anyway

matt.fellows
2021-06-03 07:28
Getting rid of Ruby would be the #1 in and of itself, let alone the other benefits

matt.fellows
2021-06-03 07:29
This is where I need help (maybe @jacek.helper has thoughts on this), but ideally, we have a separate tracking branch for the v3 release and can get it published on Nuget as a beta.

yann.courtel
2021-06-03 07:29
In that case, should we initiate a 4.0.0 version since there are many breaking changes? :slightly_smiling_face:

matt.fellows
2021-06-03 07:29
we then need a plan to maintain the current path in parallel for a period of time

matt.fellows
2021-06-03 07:29
indeed we should

pact544
2021-06-03 07:30
Yeah it'd def be v4.0.0, and could do with some proper review of the codebase as a whole given it's essentially a rewrite

yann.courtel
2021-06-03 07:30
@pact544 I am starting with the sample (API tests) to make sure they work with the V3 Pact builder (they do ^^) and adding the functions one at a time, TDD style. I can stash my work and go from master as soon as the 4.0.0 is created, no problem.

pact544
2021-06-03 07:31
Before we can release a first beta version though we need to sort out packaging up the Rust libs as a NuGet because at the moment they look at a locally compiled version

yann.courtel
2021-06-03 07:31
that's true. Almost forgot

pact544
2021-06-03 07:32
I can def have a go at that as well. The repo still contains all the old scripts for grabbing the Ruby version and stuff, so we should replace all of that also

pact544
2021-06-03 07:32
@matt.fellows I'd tried the bintray link to the released Rust versions and it just gave me a 404 though. Do you know the proper URL?

matt.fellows
2021-06-03 07:35
bintray?

matt.fellows
2021-06-03 07:35
Ahh, they are the C++ artifacts I think

matt.fellows
2021-06-03 07:35
just look at GH releases, that?s where they?re published


matt.fellows
2021-06-03 07:36
bintray is :coffin:

pact544
2021-06-03 07:38
Ah OK, I'll have a think about how best to grab those then. IIRC github supports a "latest" metatag, but it's probably best that we hard-code the version in a script somewhere anyway so it's clear when we upgrade

pact544
2021-06-03 07:39
Oh - do we only support 64bit libraries? I'd expected to see 32bit for Windows/Linux

pact544
2021-06-03 07:40
The test runner in Visual Studio runs as 32bit by default as well (who knows why) so it gives you errors unless you change from the defaults

yann.courtel
2021-06-03 07:42
I believe you can change the target processor for 64. no?

matt.fellows
2021-06-03 07:50
Might need that 32 bit then - currently there is no 32 bit build, but I assume it?s doable

matt.fellows
2021-06-03 07:50
as for the release pinning, I do that in Pact Go. I think it makes sense, because semver etc.

pact544
2021-06-03 07:51
Yeah plus keeping bindings up to date with a moving FFI target, nah thanks :smile:

matt.fellows
2021-06-03 07:51
:point_up:

pact544
2021-06-03 07:52
Right, I'll prioritise getting the native deps bundled up somehow then and we'll see how it goes

pact544
2021-06-03 09:32
Looking for opinions on packing these native deps because there are two options: 1. Like now with PactNet.Windows, PactNet.Linux.x86 etc etc so the user has to install the appropriate package for their OS a. Good - creates small packages b. Bad - it's really annoying when working cross-platform to have to have OS-specific conditionals in your csproj (e.g. you mostly work on Windows but CI runs in Docker/Linux), plus Visual Studio only updates the Windows version when doing nuget upgrades 2. Just build one PactNet.Native package which include all the OS-specific FFI libraries, and then it unpacks the correct one at compile time depending on the OS c. Good - only one thing to install and then it all just works d. Bad - big package (probably around 30MB) Opinions? I think I prefer option 2

yann.courtel
2021-06-03 09:40
I would prefer #2. Indeed, we have our local test on Windows and on the build, it's on a Linux system so more maintenance to do.

yann.courtel
2021-06-03 09:59
The support for multiple parameterized provider state is actually super easy since the rust ffi supports it. I added an API test (in the sample projects) to test the V3 specific features. I think we can add it to your work @pact544. We would leave out only the messaging part for another branch.

pact544
2021-06-03 10:15
Oh, I already did the parameterised provider states, sorry!

yann.courtel
2021-06-03 10:15
haha, it's fine, I got the code base and added the V3 Api tests ^^

pact544
2021-06-03 10:15
Cool, 2 it is

matt.fellows
2021-06-03 10:26
have you got the ?value from provider states? feature implement? Add that to the #TODO

matt.fellows
2021-06-03 10:26
Yann - are you saying you?ve added tests to Adam?s code base already?

matt.fellows
2021-06-03 10:27
I?d go with 2

matt.fellows
2021-06-03 10:27
that?s the new plan with Pact JS

yann.courtel
2021-06-03 10:27
I haven't pushed it yet (not sure I can) because the provider state middleware will have to change to validate it can get the values from them.

yann.courtel
2021-06-03 10:27
The consumer part works fine

matt.fellows
2021-06-03 10:27
nice

matt.fellows
2021-06-03 10:27
we should get you folks push access to the main repo, so you can collaborate

yann.courtel
2021-06-03 10:28
it's not super mandatory since it's not a lib problem but it's on the provider side but it would be nice to have a full API tests for V3 features :slightly_smiling_face:

yann.courtel
2021-06-03 10:28
haha yeah. Although seeing the code base up close, it will be much easier to implement the messaging part now

pact544
2021-06-03 10:29
It also makes the whole thing _so_ much easier to write

pact544
2021-06-03 10:30
Yeah I even put a `TODO` in the code exactly where it needs to go :smile:

jacek.helper
2021-06-03 10:56
Hi guys, Great news that you push forward work on V3. @matt.fellows I am happy to share my thougs/help just feeling a bit lost in this thread. There are number of technical details and questions so I am not sure on where my input can be valuable.

matt.fellows
2021-06-03 10:58
yeah, it moved very quickly from ?hello? to ?here is an example working with FFI?

matt.fellows
2021-06-03 10:59
The current state is there is a working v3 compatible branch using the FFI bindings, the macro level questions are currently - what does a rollout of this look like (e.g. to nuget, branching, testing, beta testing etc.)

matt.fellows
2021-06-03 10:59
I?ve just invited you folks to join the org

pact544
2021-06-03 11:33
So I've got it all packaging up properly. The packed nuget is ~25MB and fully unpacked it would be ~75MB, but it should only unpack the ones you actually need so ~10MB

matt.fellows
2021-06-03 11:38
Awesome!

matt.fellows
2021-06-03 11:38
25mb seems totally reasonable to me.

matt.fellows
2021-06-03 11:38
When you get several hundred MB for a react project, what?s another 35 mb?

matt.fellows
2021-06-03 11:38
What do we think about using a project board to track the work e.g. https://github.com/pact-foundation/pact-net/projects/1?add_cards_query=is%3Aopen

matt.fellows
2021-06-03 11:39
you don?t have to convert them into issues

matt.fellows
2021-06-03 11:39
I?d suggest for big items where we may want a collaborative/review process, we could convert into issues. For smaller tracking, the task itself might be fine

matt.fellows
2021-06-03 11:39
Currently it?s hard to get a ?snapshot? as to where things are at

pact544
2021-06-03 11:40
Yeah we probably need to add x86 at least for Linux if not Windows as well, and maybe the new osx processor also. That's probably double the size

matt.fellows
2021-06-03 11:40
If you like, I can put basic placeholder cards for all of the things at a macro level might need to get done. It doesn?t mean we can?t release a package before then of course

pact544
2021-06-03 11:40
Maybe even MUSL for Linux so it works in Alpine containers

pact544
2021-06-03 11:41
And ARM

pact544
2021-06-03 11:41
:joy:

matt.fellows
2021-06-03 11:41
M1?

pact544
2021-06-03 11:41
Yeah

matt.fellows
2021-06-03 11:42
I think Ron has the musl stuff covered, at least, he has a process to generate musl artifacts - for that exact reason

pact544
2021-06-03 11:43
For now I'll just leave it at x64 but it's just a few lines of copy/paste to add further arch once they're supported

jacek.helper
2021-06-03 11:50
Few thought from me: 1. I think it will be easier to drive a changes and collaborate, especially from the meta level point of view if we have task, issues related to some kind of plan. Like GitHub issues, which can be used also for release notes. It will be also more transparent for others users, what they can expect and in which order 2. In my maybe not pragmatic World I thought that we will do that in two steps: Moving to Rust, adding v3 support. Which will be first that is relative. Moving to Rust itself should be an internal binary change, with still same public interface, we should be able to avoid breaking changes. 3. Although I didn't see a code changes, it looks like a big thing worth to major bum up 4. In terms of supporting two version (not sure if If I chain good understanding ). When we will release new 4.0.0 version, then we should only fixed bug for older one 5. Beta version - very good idea for such change. We just need to think about asserts here e.g. how long, is there anyone which we want to ask directly about test and so on. It will be good to know under which condition we want to promote beta version. 6. I never use term of FFI, but if you think about calling RUST fro c# then we may have invest some time for more narrow compering to end to end, integration tests suit. They will just focus on such integration 7. Branch like 4.0.0 sounds good to me 8. Nuget release, depend on how we want to test it, we may even start with alpha version (`4.0.0-apha001, 4.0.0-apha002`), next beta, and final one. Personally I am using GitVersion for this. I am almost sure that you have think about all of this stuff, so sorry if I didn't add anything new. At least just share my broad understanding.

matt.fellows
2021-06-03 11:52
That?s great Jacek!

yann.courtel
2021-06-03 11:54
I think the beta version for a 4.0.0 sounds reasonable. As far as breaking changes, I think there will be quite a few :smile:

pact544
2021-06-03 11:54
> Moving to Rust itself should be an internal binary change, with still same public interface, we should be able to avoid breaking changes. This particular bit isn't possible unfortunately. The semantics of how the mock server works have changed quite substantially so the old API no longer works

yann.courtel
2021-06-03 11:55
Since the PACT v3 specs are also encapsulating the old specs, it's not that big of a deal to rewrite these parts.

matt.fellows
2021-06-03 11:56
1. Yes I would love this also. Primarily, I can to help drum up beta users and drive adoption. I suggest we use https://github.com/pact-foundation/pact-net/projects/1?add_cards_query=is%3Aopen 2. We?ll probably go down a path similar to that in JS Jacek, but only because I need to give Tim some time to fully appreciate the power of the new interface and changes that migt be required. It?s doable on the provider side, but I just don?t think it is worth it for the consumer. I think a breaking API change is personally OK - at least, if we do a big breaking change, now is the time 3. yep! 4. agree 5. Cool - happy to facilitate and get beta users on (via our many comms channels) 6. Yep. we discussed perhaps some BDD/Cucumber scenaros for this 7. :thumbsup: 8. Sounds good. I?d suggest `4.0.0-alpha+buildversion` because it will be easy to see as a human with an incrementing build number (i.e. when it comes to telling people they can immediately see)

matt.fellows
2021-06-03 11:56
We need to differentiate v2 pact specification support against the current Pact .NET interface. v2 _must_ be supported, but the previous .NET API need not

pact544
2021-06-03 11:57
The version would need to be `4.0.0-alpha.1` instead of `+` because `+` isn't taken into account by SemVer (i.e. 4.0.0-alpha+1 and 4.0.0-alpha+2 are considered equivalent)

yann.courtel
2021-06-03 11:57
yes and getting alpha version could mean more branch and PR which would be easier to add small features

matt.fellows
2021-06-03 11:58
ah yes sorry. that?s exactlyp what we do with Pact JS

matt.fellows
2021-06-03 11:58
I originall had the gitsha above, then decided against but didn?t correct

matt.fellows
2021-06-03 11:58
glad we?re on the same page :laughing:

matt.fellows
2021-06-03 11:59
I?d also highly suggest we follow conventional commits so we can automatically generate release notes

matt.fellows
2021-06-03 11:59
we do it on practically all other Pact repos, and it?s lovely

jacek.helper
2021-06-03 12:02
@pact544 do http://nuget.org still have a problem with proper sorting versions like `4.0.0-alpha.9` and `4.0.0-alpha.12` Internally we are using JFrog artifact On*-*Prem, which has this issue. In this case we may want to consider adding a padding zeros like `4.0.0-alpha.001`

jacek.helper
2021-06-03 12:04
Sorry for JFrog link, That was not intended

pact544
2021-06-03 12:04
Nah nuget supports proper semver2

greg595au
2021-06-03 12:18
@pact544 you are awesome :slightly_smiling_face:

jacek.helper
2021-06-03 12:25
@matt.fellows > We?ll probably go down a path similar to that in JS Jacek, but only because I need to give Tim some time to fully appreciate the power of the new interface and changes that migt be required. It?s doable on the provider side, but I just don?t think it is worth it for the consumer. I think a breaking API change is personally OK - at least, if we do a big breaking change, now is the time My motivation was giving users, which do not need V3 better Pact implementation, without a need for adjusting to breaking changes, which maybe costly for them @pact544 > This particular bit isn't possible unfortunately. The semantics of how the mock server works have changed quite substantially so the old API no longer works  By old API you mean old pact-net public API? Could you provide some examples, where you think it will be hard to keep current public API? Do not take me wrong, I do not want to be stubborn on this, I just think that even if we cannot avoid breaking change we should think twice before we adding yet another one. This will allow us to simplify migration steps, gain more new version of pact-net clients, especially if they do not have motivation to use V3.

yann.courtel
2021-06-03 12:35
@matt.fellows the injected values for provider states is a 3.5 specs feature right?

matt.fellows
2021-06-03 12:35
It's kinda a not in a spec feature, i think

matt.fellows
2021-06-03 12:35
But simple to do

yann.courtel
2021-06-03 12:35
Okay I see

matt.fellows
2021-06-03 12:36
You just need to return a hash from a provider state endpoint

pact544
2021-06-03 14:19
@jacek.helper Yeah no probs - so in the old API you start the server in a pre-test setup fixture, then you setup each interaction (which configures the server in real time), verify the interaction (which might fail) and then you clear the interactions at the end of the consumer test so that the next one starts with a "clean" server. i.e. you start the server once and call setup/verify/clear on it many times. The new Rust backend is the opposite way round. First you setup the interaction(s) that you want to perform, then you start the server, verify and shut it down again in each test. So that means in a test suite with 20 interactions you will start and stop a mock server 20 times, whereas previously you'd start it only 1 time and just interact with the same server 20 times. If you try to interact with the Rust server after you've started it, the changes that you make have no effect. It takes a snapshot of the interaction state at the point you create the server and that's it, it's fixed for the lifetime of that server. That means the old API no longer makes any sense - you can't change the server after you've started it and there's no notion of "clear".

pact544
2021-06-03 14:23
In rough psuedo code it's: ```Old Ruby way: [TestFixtureSetUp] public void Setup() { server.Start(); // once at the start before any interactions happen } [TestFixtureTearDown] public void TearDown() { server.Stop(); // once at the end when every interaction finished } [Test] public void Interaction1() { server.UponReceiving(...).WillRespond(...); client.CallServer(); server.Verify(); server.Clear(); // clear the state ready for the next interaction that reuses the same server } [Test] public void Interaction2() { server.UponReceiving(...).WillRespond(...); client.CallServer(); server.Verify(); server.Clear(); } New Rust way: [Test] public void Interaction1() { rust.UponReceiving(...); // setup must be done _before_ you start the server using (var server = rust.StartServer()) // every interaction starts and stops its own server { client.CallServer(); } // at the end of this using block the verify happens and the server shuts down. There is no Clear } [Test] public void Interaction2() { rust.UponReceiving(...); using (var server = rust.StartServer()) { client.CallServer(); } }```

pact544
2021-06-03 14:28
So, yeah, in order to adopt Rust as a backend, even if you tried to make the absolute minimum changes possible, our existing users would already have to rewrite all of their tests for a large breaking change

pact544
2021-06-03 14:29
Secondly, the Rust backend accepts arguments very differently from the Ruby backend (it's much more fine-grained) so you have to make other breaking changes to the way that interactions are set up (specifying headers/query strings/etc). All in all, it's a large breaking change to move to Rust which requires users to rewrite their tests

pact544
2021-06-03 14:30
Thirdly, the way that PactNet is currently distributed is via OS-specific nuget packages which wrap the Ruby dependencies. We can't repurpose those to use Rust because otherwise older versions of PactNet could very well break. The actual NuGets themselves need to change (as in, new names) in order to prevent older pactNet versions from breaking

pact544
2021-06-03 14:32
I've pushed these changes up now. There's a script to run which grabs the Rust deps and puts them in the appropriate folders (replacing a similar script which grabbed the Ruby deps) and then it should all just work

pact544
2021-06-03 14:32
I've created a little sample project to test installing the nuget and it all restores fine and finds the FFI libraries, but there's a really weird problem with the API that I can't quite put my finger on so currently it definitely doesn't work

pact544
2021-06-03 14:33
When you try to write a consumer test it tries to call an `internal` method instead of calling the `public` version of that method, so it gives you an access exception

pact544
2021-06-03 14:34
The request sets up fine but once you call `Willrespond` it throws an exception about trying to call the internal versions

pact544
2021-06-03 14:34
I can probably just rename the internal method and it'll be fine though

yann.courtel
2021-06-03 14:39
Thanks a lot @pact544 that's weird

pact544
2021-06-03 14:42
Nope, this is super weird. It's using the concrete implementation instead of using the interface version of the method call. I think it might only be a problem in Release mode as well :open_mouth: I've renamed the internal versions to have `Internal` at the end and now it just says it can't find it at all: ```$ dotnet run Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'PactNet.Native.NativeRequestBuilder' does not contain a definition for 'WillRespond' at CallSite.Target(Closure , CallSite , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0) at pactnet_test.Program.Main(String[] args) in C:\temp\pactnet-test\Program.cs:line 74 at pactnet_test.Program.<Main>(String[] args)``` I honestly think that's a bug in the .Net Core runtime

pact544
2021-06-03 14:43
It compiles absolutely fine but then fails at runtime :open_mouth: If it was a problem it shouldn't even compile

yann.courtel
2021-06-03 14:43
The WillRespond though is tied to your interface, are you sure it calls the one using the correct abstraction?

pact544
2021-06-03 14:43
Like I say, it wouldn't compile if it wasn't the correct one. It only fails at runtime

yann.courtel
2021-06-03 14:44
Not necessarily, if the call is made at runtime

pact544
2021-06-03 14:44
Look at this really weird hint in Visual Studio though

pact544
2021-06-03 14:44
It thinks its become a dynamic!

yann.courtel
2021-06-03 14:44
where is your example at?

pact544
2021-06-03 14:45
Just in a little local console app to test the nuget restore

pact544
2021-06-03 14:45
Literally just `dotnet new console && dotnet add package PactNet.Native` after I've built the nuget locally, then paste the example in from the integration tests

pact544
2021-06-03 14:46
Compiles fine, blows up at runtime

pact544
2021-06-03 14:46
That shouldn't even be possible

yann.courtel
2021-06-03 14:46
It's strange on my end, the auto-completion doesn't even pick up the WillRespond... even with Resharper

pact544
2021-06-03 14:47
I'll have a play around with it and see what happens

pact544
2021-06-03 14:47
Probably because I've got 2 explicit interface implementations with clashing names

yann.courtel
2021-06-03 14:47
yeah prob

yann.courtel
2021-06-03 14:48
We should prob add to each Request builder the interface they need

yann.courtel
2021-06-03 14:48
but that would be a chaining of the interface...

yann.courtel
2021-06-03 14:48
Like IRequestBuilderV3 : IRequestBuilderV2

yann.courtel
2021-06-03 14:49
Not sure it's the design you intended

pact544
2021-06-03 14:51
You can't do that otherwise as soon as a v3 builder calls a v2 method it'll get back a v2 builder instead of a v3 one

yann.courtel
2021-06-03 14:53
the only probleme I have is with WithJsonBody...

yann.courtel
2021-06-03 14:55
The auto-completion works when I pass a dynamic directly from the test function and not as a dynamic class variable... I don't know what's going on...


yann.courtel
2021-06-03 14:58
What I got from this is that the line where your dynamic is defined matters, so in your case, maybe add it inside your test instead of an instance variable.

pact544
2021-06-03 15:06
Ah gotcha :thumbsup: So yeah sounds like a .Net runtime bug

pact544
2021-06-03 15:06
Like it doesn't become "undynamic" again

yann.courtel
2021-06-03 15:06
yep, well that might be a limit

yann.courtel
2021-06-03 15:07
the dynamic's intention is to be used dynamically and not "stored" per say. That's what I got from this, but I didn't know it would have consequences like you had at the runtime!

pact544
2021-06-03 15:08
Ha, yep that worked fine!! Literally just moved the variable to be inline instead of in a static field and it now works fine

yann.courtel
2021-06-03 15:08
Great

pact544
2021-06-03 15:08
Phew!!!

pact544
2021-06-03 15:09
Thought I'd seriously fucked up the API somehow then

yann.courtel
2021-06-03 15:09
no, thanks god

pact544
2021-06-03 15:10
Well in that case, enjoy the new nuget support :smile:

yann.courtel
2021-06-03 15:10
haha thanks

yann.courtel
2021-06-03 15:15
I tested the script on my end and it works fine!

pact544
2021-06-03 15:16
Niiiice

pact544
2021-06-03 15:16
We need to get the CI going properly now all the tests work

yann.courtel
2021-06-03 15:16
Compilation is fine, running all tests, there are a few mishap... maybe the dynamic

pact544
2021-06-03 15:16
Especially with the cross-platform GitHub Workflows thing because I can't test on OSX atm

pact544
2021-06-03 15:17
Ahhhh, you know why that is? `mock_server_logs` is on `master` for the FFI library but not in the latest released version so that binding is failing now we've switched over

yann.courtel
2021-06-03 15:18
impossible to find the mock_server_logs

pact544
2021-06-03 15:18
Yeah when I was compiling `master` locally that worked fine, but the latest release doesn't have it

yann.courtel
2021-06-03 15:18
it fails the Api test for the same reason

pact544
2021-06-03 15:18
Needs a new FFI release

yann.courtel
2021-06-03 15:18
well, it looks like just one thing

yann.courtel
2021-06-03 15:19
Maybe Matt or Ron can do it

yann.courtel
2021-06-03 15:24
Nice summary. I was thinking we could wrap the using into a more userfriendly method like Verify(() => client.myAction... )

yann.courtel
2021-06-03 15:26
Well, seeing you need the MockServerUri, it will have to be into a specific fixture class to work.

yann.courtel
2021-06-03 15:27
Still, it's much easier to write the interactions like that

pact544
2021-06-03 15:42
Yeah you can't know the mock server URL ahead of time because you generally use a dynamic port so you need to wait until it's started before you can construct your client

yann.courtel
2021-06-03 15:43
yes, I was just thinking on the end user, using it inside a fixture class which takes care of the instanciation of the server and which port it uses will make the test even easier to write.

yann.courtel
2021-06-03 15:43
I don't know if the lib pact-net is the place to do it though :slightly_smiling_face: prob more on the consumer side

pact544
2021-06-03 15:45
Class fixtures run once before any test runs though (which is impossible because then you can't add interactions to it): https://xunit.net/docs/shared-context

pact544
2021-06-03 15:45
You need to use the ctor/dispose approach

yann.courtel
2021-06-03 15:46
yep, as a custom one you can

yann.courtel
2021-06-03 15:46
but again, that's more of a consumer-side optimization

pact544
2021-06-03 15:46
You need to add the interaction before you start the server though

pact544
2021-06-03 15:47
You literally have to start the server inside each test so that you can set up your interactions before starting it

pact544
2021-06-03 15:47
I still don't think that's the best approach, but that's the way the Rust core is so this is the API you kinda naturally end up with in PactNet

yann.courtel
2021-06-03 15:48
yeah, we will see once we have the version up

yann.courtel
2021-06-03 15:48
I'm off, have a nice day and thank you for the effort today!

pact544
2021-06-03 15:49
No probs dude, have a good evening

pact544
2021-06-03 15:57
I've accepted the invite into the pact-foundation but I'm not sure that actually gives me write access to anything :slightly_smiling_face: How do we want to proceed with getting my changes merged over into a proper branch in the pact-net repo?

jr.jenks
2021-06-03 16:07
has joined #pact-net-development

jacek.helper
2021-06-03 16:22
@pact544 regarding to your pseudo code. That is not how I see this I think I understand your intention, but I still think that it should be possible. In pubic interface there is nothing about starting or stoping so I am not sure if I will expose something like `StartServer` or something similar and make this public concept, it can be just technical details. Below I try to show how I am using currently pact-net: ```[OneTimeSetUp] _pactConfig = new PactConfig      {        SpecificationVersion = PactConfiguration.PactSpecificationVersion,        PactDir = Path.Combine(testBinDirectory, PactConfiguration.PactsDir),        LogDir = Path.Combine(testBinDirectory, PactConfiguration.PactLogsDir),        Outputters = new List<IOutput> { new NUnitPactOutput(Console.Out) }      }; [SetUp]      _pactMockServiceSetUp.MockService.ClearInteractions(); [OneTimeTearDown]      _pactMockServiceSetUp.PactBuilder.Build();      _publisher().Publish();       [Test] MockService        .Given($"Foo")        .UponReceiving($"Bar")        .With(_tfp.CreateValidRequest())        .WillRespondWith(_tfp.CreateSuccessfulResponse(links));        _myCommunicator.CallSomeAction(        .Should()        .BeEquivalentTo(new Invoice("http://dummy"));        _pactMockServiceSetUp.MockService.VerifyInteractions();``` In my example if VerifyInteractions will have this whole stuff with starting and stopping server will works for me. > Thirdly, the way that PactNet is currently distributed is via OS-specific nuget packages which wrap the Ruby dependencies. We can't repurpose those to use Rust because otherwise older versions of PactNet could very well break. The actual NuGets themselves need to change (as in, new names) in order to prevent older pactNet versions from breaking Just to make this clear you talk about `PactNet.Windows` package? If so you have right, which is not perfect in my opinion. I am not sure how it is done in details now. However if I will do that in a past or plan some future changes like this one. I will try to separate public pact-net interface concept form engine realization (ruby, rust) details. Just imagine how cool it will be when we will not have to change public interface when we will move to yet another engine realization under the hood. Or imagine if same pact-net client code can once works with rust and once with ruby. To do that we can change a bit how stuff are set up and allow clients to choice core realization by DI.

pact544
2021-06-03 16:53
Two problem with your example there (if it was using the rust backend): ? at the point you make your client call the server is not started, so it will fail ? you don't know the port of the mock server until after you've started it, so if the verify does the start then how can your client know the port to call? Your client can only be constructed after the mock server has started so that you know its URL. That's not the case with the Ruby version. In Ruby the server starts first in your one time setup so you know the URL straight away, and it's always running so your client can always call it. In terms of not changing the public API when we swap provider backend, I think the changes I've made make that really easy now :+1: I've created a PoC remote backend as well, but it's not implemented yet. We could easily create a Ruby backend as well.

jacek.helper
2021-06-03 18:50
> at the point you make your client call the server is not started, so it will fail You have right. However I am still not convince to expose details behind rust server implementation. I think it should be a way to hide this. > you don't know the port of the mock server until after you've started it, so if the verify does the start then how can your client know the port to call? You want to say that i cannot set up mock uri in advance? Why in Rust implementation I cannot specify a port? It doesn't sounds right to me and it is probably related to Rust. By the way starting some external service and stopping it in each test case separately doesn't look like super thing from resource/performance point of view. Is there any way it can be started once, or at least per test suit?

jacek.helper
2021-06-03 18:55
Sorry if this will sounds badly that is no my intention, I just would like to know why we wan to move to Rust in the first place. Does PactBroker or PactBroker client plan to do the same or they will stay with ruby engine version?

jacek.helper
2021-06-03 19:02
The last thing from me today. What about the last feature, which we have added few weeks ago, https://github.com/pact-foundation/pact-net/pull/277 ? Did you think how these two things can co-exist, since it is hard to imagine that somebody will start and stop remote mock server in each test case.

pact544
2021-06-03 21:41
Yeah, so to answer those I think we can still support the remote server no problems. It's probably best checking the new API on my branch to see how it would be possible, but the internals of how a particular server works are entirely contained within the server's own nuget, so you don't tell the server to start or stop. In terms of starting the mock server only once and sharing it, it's not possible. I implemented it that way at first and spent two days scratching my head before I worked out it's impossible. I looked through the Rust source code and found it takes a snapshot of the state at the point it starts so you can't start it before you've set up your interactions. @uglyog and @matt.fellows advised that the approach taken in all the other language integrations is to start and stop the server for each test, so I've mirrored that on the new PactNet API. That's the only way the Rust version can work at the moment.

matt.fellows
2021-06-03 23:27
> Secondly, the Rust backend accepts arguments very differently from the Ruby backend (it?s much more fine-grained) so you have to make other breaking changes to the way that interactions are set up (specifying headers/query strings/etc). All in all, it?s a large breaking change to move to Rust which requires users to rewrite their tests It?s probably the way .NET works, but in Pact Go, I was able to swap out Ruby with Rust without any breaking changes. I chose to make a few breaking changes simply because I think the interface is made clearer. The ?verify? step always accepted a function that was given a context (i.e. the mock server details). So at the least, that would have needed to change for .NET

matt.fellows
2021-06-03 23:28
> Yeah, so to answer those I think we can still support the remote server no problems. It?s probably best checking the new API on my branch to see how it would be possible, but the internals of how a particular server works are entirely contained within the server?s own nuget, so you don?t tell the server to start or stop. cool!

matt.fellows
2021-06-04 01:20
> In terms of starting the mock server only once and sharing it, it?s not possible. I implemented it that way at first and spent two days scratching my head before I worked out it?s impossible. I looked through the Rust source code and found it takes a snapshot of the state at the point it starts so you can?t start it before you?ve set up your interactions. If that becomes a performance issue that we can?t get to the bottom of, i?m sure we?ll find a way to support the stateful server (or something similar)

matt.fellows
2021-06-04 01:20
I?ll add you to the repo, I think the invite has to be accepted first

matt.fellows
2021-06-04 01:23
done

pact544
2021-06-04 06:30
I've thought about that performance issue that I'd noticed and I'm now suspicious it's not the Rust core that's the problem. I'm not really seeing a performance problem in my integration tests which just go direct to the interop code, but I am seeing it when I run the sample consumer tests. However, the thing that's definitely made me think it's more the .Net side is that the consumer tests example also compiles really slowly (seemingly for no reason, it barely does anything)

matt.fellows
2021-06-04 06:38
ok that?s good to know

matt.fellows
2021-06-04 06:42
I just wrapped the node test in a loop that runs the full cycle 500 times, and it runs in sub 3s > ? pact-js git:(spike/ffi-provider) ? time node src/native/test.js > node src/native/test.js 2.11s user 0.29s system 98% cpu 2.423 total > ? pact-js git:(spike/ffi-provider) ?

jacek.helper
2021-06-04 06:50
@pact544 thanks for details. Could you share your branch name, maybe when I feel better I will take a look and share some constructive thoughts.

pact544
2021-06-04 07:19
I've created a draft PR against the proper pact-net repo with my work so far, and written up some of the rationale of the new design within it: https://github.com/pact-foundation/pact-net/pull/297 Please review, and then we can merge it (to the new `feature/4.0.0` branch) to use a base going forwards

pact544
2021-06-04 07:19
@jacek.helper - Just raised the whole thing as a draft PR here: https://github.com/pact-foundation/pact-net/pull/297

pact544
2021-06-04 07:23
Definitely worth changing the setting to hide whitespace changes :open_mouth:

matt.fellows
2021-06-04 07:28
I?m wondering that because the change is so big, the best first step might be to get it merged into a branch so everyone can contribute from there. otherwise I fear the conversation will quickly convert to bikeshedding

matt.fellows
2021-06-04 07:29
But, what a way to end a week (well, for those of us in the future :stuck_out_tongue: )

pact544
2021-06-04 07:37
Ha, thank you :smile:

pact544
2021-06-04 07:38
Yeah I thought the same. It could get absolutely massive and end up stalling otherwise. Didn't want to just yeet it in the main repo though :smile:

pact544
2021-06-04 07:39
Probably just best to review for at least any "omg, def don't do that" changes :smile:

yann.courtel
2021-06-04 08:29
Yes, that's what we agreed on. The message part and the remote mock server is going to be another big chunk of code :slightly_smiling_face:

pact544
2021-06-04 08:29
OK, shall we just merge it then?

yann.courtel
2021-06-04 08:30
Let's do the code review then

pact544
2021-06-04 08:30
It's on a feature branch anyway, not direct onto `master`

yann.courtel
2021-06-04 08:30
I hope @pact544you had time to have some breaks at the pace you were going XD

pact544
2021-06-04 08:30
So yeah cool, if you can give it the once over for any obvious big problems and we can merge it as a base to work on going forwards

yann.courtel
2021-06-04 08:34
yep, the few things I would do it before the merge 1. Split the interfaces into separate files. Maybe do some folder reorganization, like with functional names, Request / Builder / etc. 2. Small code cleanup feature like organizing the usings 3. Use the simpler using declaration (in the tests) introduced in the latest c# version 4. I don't know how you feel about naming convention for the class variable with or without '_' which will allow you not to explicitly have 'this' everywhere. Mostly what I'd call cosmetic changes :wink: For the rest, it's still an alpha version so we can reorganize things later on.

pact544
2021-06-04 08:42
> Split the interfaces into separate files. Maybe do some folder reorganization, like with functional names, Request / Builder / etc. I didn't do this purely because it would make all the imports annoying for the end user. They'd have to import like 5 namespaces just to run a single consumer test

pact544
2021-06-04 08:43
> Small code cleanup feature like organizing the usings Do you have an examples of that one? I have an on-save trigger to sort/remove usings so they should all be correct just by default :smile:

yann.courtel
2021-06-04 08:44
I see. I mean, it's just on Visual Studio, you right-click on your solution and do a code cleanup, just to avoid anything super obvious ^^ let the IDE do the work.

yann.courtel
2021-06-04 08:45
Or maybe it's just my resharper complaining hehe. It can be annoying lol

pact544
2021-06-04 08:47
Just done the cleanup and pushed. It only really trimmed a bit of whitespace here and there though :smile:

yann.courtel
2021-06-04 08:48
Sounds like a major breaking change ^^

pact544
2021-06-04 08:49
Not another one :joy:

pact544
2021-06-04 08:50
I needed to get it done this week. The permission to work on it basically full time was only for 2 weeks from my boss and that ends today :open_mouth: Then I'm on vacation Mon-Fri next week, but I'll check in here occassionally

yann.courtel
2021-06-04 08:51
ah ok! Sounds good.

yann.courtel
2021-06-04 08:51
In this case, let's have it merge asap and we could go from the feature branch

pact544
2021-06-04 08:57
Cool, I'll merge now if the comments are more organisation/cosmetic that we can always sort easily later

yann.courtel
2021-06-04 08:58
absolutely

pact544
2021-06-04 08:58
Would you be able to put a quick comments on the PR just so it doesn't look like I'm merging without any review? :smile:

pact544
2021-06-04 08:58
Even just an "I approve" :smile:

yann.courtel
2021-06-04 08:58
can you link the PR plz? No Problem :)

yann.courtel
2021-06-04 09:02
all good

yann.courtel
2021-06-04 09:02
I put the remaining comments so we don't forget them :wink:

yann.courtel
2021-06-04 09:03
I'll present your work to my team to see if they have comments also. We will go from the 4.0.0 feature branch then. Very nice job!

pact544
2021-06-04 09:04
Done :thumbsup:

pact544
2021-06-04 09:04
Now I'll fix the CI

yann.courtel
2021-06-04 09:06
Strange CI problem. looks like a ps script is not there

pact544
2021-06-04 09:08
Yeah it'll be looking for the script to grab the Ruby libs and stuff

pact544
2021-06-04 09:09
I'll have a look at moving it to GitHub Actions so we get better decoration, and then we can also run the CI on OSX

yann.courtel
2021-06-04 09:09
ah ok, indeed

yann.courtel
2021-06-04 09:12
We will need to also separate the Interop class into its own file into prob a MockServer folder for future maintenance. I prefer functional folder organization rather than purely technical.

pact544
2021-06-04 09:13
That one was deliberately a private inner class so that the outer class could deal with the weird concerns of interop (like wrangling `IntPtr` objects to and from strings)

yann.courtel
2021-06-04 09:14
I see, accessibility over maintenance. I can understand why you saw it that way

pact544
2021-06-04 10:46
Bah, I've got the cross-platform CI going on Windows/Mac/Linux but unfortunately the provider sample is .Net Framework only so it won't build on Linux/Mac. That needs converting to .Net Core really because it demonstrates using it with legacy http://ASP.Net instead of modern http://ASP.Net Core. I think a Core example would be far more useful

pact544
2021-06-04 13:23
Raised a draft PR for converting the sample from ASP .Net Legacy and .Net Framework (Windows only) to ASP .Net Core and .Net Core 5 (cross-platform). At the moment it's failing but because there's still no way to get logs out of the verifier FFI I'm not really sure why...? I imagine it's something do with auth or something. I can curl the API via `curl` and it looks OK so dunno what's wrong. https://github.com/pact-foundation/pact-net/pull/298

yann.courtel
2021-06-04 14:19
Hey everyone, so I started in the message integration but I am a bit stuck on how the different method of the FFI should be called. We have a new_message_pact and a new_message method in the FFI on the pact mock server lib. I'm assuming the first to be called to be the new_message_pact but then when I want to specify the version with the with_specification method, it expects a PactHandle not a MessagePactHandle. @uglyog @matt.fellows Some questions: 1. do we need to call the with_specification method in case of a message creation? (prob not) 2. Is this workflow correct a. Call the new_message_pact method to get the handle of the pact message b. Call the new_message method with the previously created pact message handle c. Call any of the method that takes a message handle in parameters (such as message_expects_to_receive or message_given) d. Finally call the write_message_pact_file with the pact message handle (not the message handle) to create the final pact file Thank you!

pact544
2021-06-04 15:07
Yep that workflow sounds right to me. It's the same as the request/response message flow except that has PactHandle and InteractionHandle instead of MessagePactHandle and MessageHandle

pact544
2021-06-04 15:27
PR to get CI working with cross-platform build and test for Windows, Linux and Mac: https://github.com/pact-foundation/pact-net/pull/299

pact544
2021-06-04 20:43
The performance problems I've seen appear to only be on Windows, and potentially even only on my work laptop. It has some crazy security software on it so I guarantee it's that. The consumer tests take ~3s each on my work laptop, but on my personal laptop running Ubuntu 20.04 they run in <200ms total :open_mouth: Lightning fast. I think we can conclude that there's no performance problems stopping and start the mock server for each test. On average we're talking ~20-30ms per test on Linux


matt.fellows
2021-06-05 06:19
but yes, what you said Yann

uglyog
2021-06-05 06:21
`with_specification` is only needed if you want to change the default, which is V3

greg595au
2021-06-05 07:58
hi everyone.. sorry I have been out of this for a bit and have some catching up to do, have we got a common code repo/branch.

greg595au
2021-06-05 08:04
is anyone opposed to me approving/releasing Adams Replace AppVeyor CI?

greg595au
2021-06-05 08:06
:point_up: belay that = we appear to be on Feature/4.0.0

pact544
2021-06-05 09:37
I'm happy as long as you're happy :+1: We probably need to decide how we're doing contributions and stuff. Like I assume it's not ok to merge stuff before it's been reviewed and we're gonna follow a PR model. There aren't many of us though so getting reviews may be a bit tricky.

pact544
2021-06-05 09:39
Yeah we can rename that if we want, that's just the name a came up with for a start. Didn't want to merge to master given it was still a work in progress at the time (well, still is I guess)

greg595au
2021-06-05 09:49
would a round robin approach help?

matt.fellows
2021-06-05 10:08
Let's aim for a single thumbs up into that working branch. Releases/master we can talk about in due course

matt.fellows
2021-06-05 10:09
At this stage, high velocity decision making should be the priority - I know that contributions/focus/time is very much dependent on things outside of our control, so let's capitalise on the energy while we can

matt.fellows
2021-06-05 10:10
The earlier we can get into the hands of early adopters for feedback the better

pact544
2021-06-05 10:10
Yep sounds good to me. Try and get some PRs in and turn them round as fast as we can into the 4.0 branch

matt.fellows
2021-06-05 10:11
Shared understanding is also important though so we can get some continuity

pact544
2021-06-05 10:11
Next thing I think is getting the CI to build alpha releases or something so we can get people testing. The whole thing should now work on all OSs, and it's not a big job to get the artifacts building properly

matt.fellows
2021-06-05 10:35
I?ve just added a branch protection rule to enforce the above. Let?s see how it goes

matt.fellows
2021-06-05 10:36
On any PR if you want to review, head to ?files changed?, hit ?review changes? and add your review. It won?t be mergeable until at least 1 reviewer approves

matt.fellows
2021-06-05 10:37
It also will require any conversations (i.e. feedback with requests) to be resolved

greg595au
2021-06-05 10:49
agree,, we can deal with all this over the coming days.. btw - noice progress

jacek.helper
2021-06-05 10:50
@pact544 I tried to take a look on your changes, share some thoughts, but I cannot build solution. I am ending with following error ```Severity Code Description Project File Line Suppression StateError MSB3030 Could not copy the file "pact-net\build\windows\x86_64\pact_mock_server_ffi.dll" because it was not found. PactNet.Native C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets 4964``` I can only suspect that it is has something to do with `download-native-libs.sh` . Do you expecting people do fire this before building solution? Is it a temporary solution? Sorry if I missed some of your previous info about this.

matt.fellows
2021-06-05 11:03
Rust integration / v2.x.x project board https://github.com/pact-foundation/pact-net/projects/1

pact544
2021-06-05 12:43
Yeah so you'll need to run that to pull down the required dependencies (the Ruby version required a script also). The CI does it automatically and we can always add a targets file to do it

jacek.helper
2021-06-05 12:47
Well, maybe I am wrong, but I did couple of code reviews and I never have to run by hand any script. Maybe you can consider packing these dlls into nuget packages or at least run your script as a part of build process?

pact544
2021-06-05 13:09
Yeah like I say, the CI does it already and we could add a targets file to automate it locally

tjones
2021-06-05 13:36
Do you mean v4?

matt.fellows
2021-06-05 13:50
Yes.

matt.fellows
2021-06-05 13:50
Awesome, I pinned it too

matt.fellows
2021-06-05 13:51
(v2.x.x is the golang next major)

jacek.helper
2021-06-05 14:20
Ok. Will it be listed as nuget dependency ? Do not take me wrong It definitely can work, but it would be problematic in some cases as well. For instance I am working for enterprise where each dependency has to be approved in advance. As part of this proces usually nugts with not transparent dependencies, not explicitly listed as project are rejected. Even if it will be accepted it must goes to our nuget repo in this case jfrog artifactory. Now all our Devs envs and CI are only based on it, cannot download additional external deps. So for case like this it I think it will be much batter if this dependencies will be manage by nuget with proper approach to version especially when we already have DLLs. Otherwise Devs in company like my will not be able to use it, unless I am missing something.

pact544
2021-06-05 16:16
Yes the native deps are bundled in to the PactNet.Native nuget

jacek.helper
2021-06-05 17:00
Hmm, I am feel a bit lost here. Is there any description of your new approach to project organization, packages and etc (I have through this one https://github.com/pact-foundation/pact-net/pull/297)? It will help in my case. If there will PactNet.Native package then I think it will work in above case. Just two questions: 1. Should script `Publish-StandaloneCore-Releases.ps1` works? It looks like it is missing PactNet.Windows.nuspec 2. How you see `PactNet.Native` package? What if for some reason we will decide to add or move to different core? Did you think maybe a more dedicated name like `PactNet.Native.Rust` ?

jacek.helper
2021-06-05 17:09
My last question for today. I see that for some reason you have decide to bundle all dependencies together. I think i go through discussion on this, seen arguments about size and simplicity in some cases, but didn't spot arguments or scenario when someone will only use single os from start to end. That is not about size itself but about binaries which shouldn't be there. Maybe we could keep your bundled packge `PactNet.Native` but also add dedicated per OS, liek it was previously?

pact544
2021-06-05 17:31
Yeah I discussed that with the maintainers of other languages before I did it and we discussed the options. We decided the simple approach with everything embedded was the best approach. There's a thread in the channel about it where we decided that. If you don't want the deps for other OSs unpacked then you can build with a runtime identifier and it'll only unpack the required one, like `dotnet build -r win-x64`, or add a runtime identifier to your csproj file so you don't have to type that each time.

pact544
2021-06-05 18:55
Unfortunately it's not just my work laptop. My own laptop (the one that runs the consumer tests in ~150ms in Linux) takes 12s to run the same tests on Windows on the same hardware. There's definitely some kind of performance problem which only affects Windows to do with the consumer tests. The provider tests take <1ms though :open_mouth: :zap:

pact544
2021-06-05 19:16
I've updated the PR to also produce alpha nugets when code is merged to the 4.0.0 branch

pact544
2021-06-07 07:12
PR for verifying SHA sums of native artifacts when restoring: https://github.com/pact-foundation/pact-net/pull/300

pact544
2021-06-07 07:15
Argh the file paths in the downloaded checksums aren't correct so I've done a bit of `sed` to put the right names in there, but it doesn't work on OSX. That's why the cross platform CI is good though at least :+1:

yann.courtel
2021-06-07 08:08
@uglyog I see. I made an additional test without the with specification and indeed, the message has the same form. The issue will come if we need to specify a future version for the messages. The with specification will need to accept the MessagePactHandle. Thank you for the clarification! @matt.fellows I now need to "verify" the sending of the message to the code base is working. In your example, you actually didn't do it, right? This is your comment I assume. How could we enforce the verification of the message, though?

matt.fellows
2021-06-07 08:16
so the flow is actually this: 1. Call the new_message_pact method to get the handle of the pact message 2. Call the new_message method with the previously created pact message handle 3. Call any of the method that takes a message handle in parameters (such as message_expects_to_receive or message_given) 4. Call `reify` to get back the message body and provider states, with the matching rules etc. removed 5. Invoke the actual function that should handle the message, passing the message and config 6. Only if (5) does not fail (whatever is idiomatic for .NET) then you move to (&) 7. Finally call the write_message_pact_file with the pact message handle (not the message handle) to create the final pact file

matt.fellows
2021-06-07 08:17
so basically, you need to invoke the function that should receive the payload, and check if it passed/failed

matt.fellows
2021-06-07 08:17
There is no need for the rust side to do this bit, because there is nothing it can really do

matt.fellows
2021-06-07 08:17
make sense?

yann.courtel
2021-06-07 08:17
Yep, that's the workflow I add in mind

matt.fellows
2021-06-07 08:17
:ok_hand:


yann.courtel
2021-06-07 08:18
My question was can we enforce the verification? As in, adding a Verify method fo the builder for instance?

matt.fellows
2021-06-07 08:18
that?s what I do



yann.courtel
2021-06-07 08:19
ok, I see in the last example :slightly_smiling_face:

matt.fellows
2021-06-07 08:20
let me know if you have any questions

matt.fellows
2021-06-07 08:20
I?m really keen to see the interface you come up with

yann.courtel
2021-06-07 08:20
I'm going to create a branch today, specific to the messaging

jr.jenks
2021-06-07 16:21
Are there any alpha NuGets yet? I don't see anything at https://www.nuget.org/packages/PactNet.Windows

pact544
2021-06-07 17:13
At the moment I've added alpha nugets to the CI pipeline only

greg595au
2021-06-08 08:50
Hey guys i will e avail tomorrow night fr 2 hrs. 7pm to 9pm. Time to get our heads around how we setup gherkin the way we think we can

matt.fellows
2021-06-08 13:29
ha, gotta love the minor differences between bsd/gnu

matt.fellows
2021-06-08 13:29
One of the first things when I get a mac, is to add the gnu tools

matt.fellows
2021-06-08 13:29
not sure what happens when I get to M1 though

matt.fellows
2021-06-08 13:30
That?d be great. What?s a good starting point? maybe scratch together a few shapes to the gherkin?

greg595au
2021-06-09 02:36
Start with thw way a common repo is set up and a standarfised way to pull into the projects

greg595au
2021-06-09 02:36
After that we look at our testing needs and develop skeletons for each given when then

yann.courtel
2021-06-09 07:13
In specflow (BDD test in .NET) I haven't tried to grab Gherkins from a remote location or a relative path. What I am afraid of is that Specflow does some work to auto-generate an intermediary code file that does the execution of the test therefore I am not sure having a remote Gherkins is even possible. I'll investigate on my end and let you know quickly.

yann.courtel
2021-06-09 07:16
One thing that would be nice is to integrate Living doc with Specflow to see the state of the integration test at the CI.

matt.fellows
2021-06-09 07:25
I didn?t make it clear earlier by the way that I can?t make tonight

matt.fellows
2021-06-09 07:25
but I think a good starting point is getting a working artifact that can be collaborated on.

yann.courtel
2021-06-09 07:27
Sounds like a good place to start @matt.fellows. I investigated with our teams and the easier will be to embark the new scenarios as we develop the feature in each language from the centralized repo. It's not that difficult ;)

matt.fellows
2021-06-09 07:29
Yep, we don?t need to do it all at once. Any starting point we can build from this experience will be really valuable for others

jacek.helper
2021-06-09 08:20
Before we go too far it will be good to think on: 1. Testing strategy. What kind of test we would like to introduce, how they related each other. Few years ago I have been inspired by this article https://martinfowler.com/articles/microservice-testing/ . Although there is microservices concept involve, there are generic approaches, which IMHO suits to many different scenarios. 2. What kind of test type we want to represent by gherkin tests. End to end, component or integration. I am using gherkin tests mostly for component, leaving integration an unit tests for testing framework like Nunit. In this project I am mostly missing integration tests with core engine, which now will be mean Rust.

greg595au
2021-06-09 09:11
hey @jacek.helper, while we could potentially use gherkin across the board, there are situations where gherkin is seen as "getting in the way". Dev's at Platform engineering have a divided opinion about gherkin on unit testing

matt.fellows
2021-06-09 09:14
My view is that these BDD scenarios are something we could reuse as features tests across libraries to say "they've implemented Pact" and also to show the gaps. It would literally be able to be translated into a roadmap

matt.fellows
2021-06-09 09:15
Within Pact .NET we should use whatever makes sense for the project. We don't use cucumber elsewhere, for reference

greg595au
2021-06-09 09:15
yep - i believe we are looking to deomonstrate the Pact specifications

greg595au
2021-06-09 09:16
hich sort of sounds like E2E

greg595au
2021-06-09 09:22
@matt.fellows the gherkin statements would provide the specification for the non-cukes implementations

jacek.helper
2021-06-09 09:23
@greg595au I am not sure if I get fully your point. My intention is not promote gherkin as unit tests. If we want to use across libraries, fine but then it will not be better if this will not depend on engine implentation? Stub engine itself. So component tests instead of end to end. As I have mention few days ago the most missing part from my point are integration tests for engine. I would suggest to add gherkin tests, which stubs engine client classes and integration tests, which will start from the same classes. That is how we could have nice tests approach.

greg595au
2021-06-09 09:26
@jacek.helper i think we have similar thoughts here, in my point above, the team of nearly 400 devs can't agree on cucumber

greg595au
2021-06-09 09:27
so what I am aming for is - where to store the tech agnositc gherkin features

greg595au
2021-06-09 09:27
how to bring them into a project (that wants to use them)

jacek.helper
2021-06-09 09:28
Make sense

greg595au
2021-06-09 09:29
i don't feel comfortable with forcing the project to adopt, because it will be a workload they might not be able to do

greg595au
2021-06-09 09:31
on a completely unrelated note - had my covid shot yesterday started feeling a but stiff today

greg595au
2021-06-09 09:32
Unit Tests - leave them in native form, there are tools that tell us coverage

greg595au
2021-06-09 09:32
Component and Integration tests seem suited to a gherkin approach

greg595au
2021-06-09 09:33
we need to map them to the Pact Spec (and they become the acceptance criteria)

greg595au
2021-06-09 09:34
which dovetails with @matt.fellows that they would enable road map to be generated

greg595au
2021-06-09 09:35
Any thoughts from @pact544 @jacek.helper @matt.fellows

matt.fellows
2021-06-09 09:37
Will try and respond later. From memory, Adam says he's off on holidays for a week or so.

greg595au
2021-06-09 09:39
thanks matt... i'll create a couple of ideas on the location/how tonight

greg595au
2021-06-09 09:58
@jacek.helper I like Martin Fowlers work - i often refer to it myself

jacek.helper
2021-06-09 10:39
I am just after covid and during week long holiday :) . I share my thought later on :slightly_smiling_face:

greg595au
2021-06-09 10:40
no worries jacek - i'll put up a diagram to cover the basic high level ideas (where/how) we'll circle back on the test stratgey and what fits best :slightly_smiling_face:

greg595au
2021-06-09 10:44
High Level Where/How for Specs to Features and then to language specific

greg595au
2021-06-09 10:45
i am getting tired, off while I can still stand....

greg595au
2021-06-09 10:45
night everyone

pact544
2021-06-09 13:58
Yep I like the idea of a common gherkin description of the spec demonstrating what that spec can do and also how it's limited. I think you end up in an awkward situation though because the spec doesn't cover a number of things and they'll be implementation specific. For example, V2 doesn't support multiple provider states, but if the implementation allows me to try it (i.e. I can call Given twice) then am I supposed to get an error or does the second overwrite the first? The spec doesn't say, so this is an implementation detail and could vary between languages. At first I'd describe only the positive tests, because the negative tests aren't really covered by the spec. For what it's worth, the Rust implementation overwrites instead is giving an error I think.

matt.fellows
2021-06-10 00:08
ah! I?ve heard it can do that, hopefully won?t be too bad!

matt.fellows
2021-06-10 00:09
> Yep I like the idea of a common gherkin description of the spec demonstrating what that spec can do and also how it?s limited. Excellent

matt.fellows
2021-06-10 00:09
There has always been a bit of a gap between ?the spec? and ?what each language actually does?

matt.fellows
2021-06-10 00:10
The spec doesn?t cover certain features. E.g. provider injected values isn?t documented in the spec, but is a feature that is supported

matt.fellows
2021-06-10 00:10
(that might actually just be a spec coverage problem, btw)

matt.fellows
2021-06-10 00:11
but the functional behaviour of each library may change, and that is probably OK - in many cases, that is because each language itself is different and what is idiomatic for one is a terrible experience for another (this tends to be true of type safe and compiled languages vs dynamic languages)

matt.fellows
2021-06-10 00:11
so we should look to find the scenarios and features that are important and common to all, and have those in the Feature spec

greg595au
2021-06-10 00:13
Woke up this morning and stiffness is gone.. so i am not expecting to experience anything new now

matt.fellows
2021-06-10 00:14
great to hear!!

yann.courtel
2021-06-10 12:45
Hi everyone, I would hold off on the Gherkins for now until we have a stable 4.0.0 version. Let's not forget it will be a shared repo for all the languages so all contributors across all the different languages will have to agree on this. Also, as I help teams on a daily basis with the different level of tests, the BDD tests in Specflow are quite big to implement and costly to maintain. While it's a great idea, it is IMHO, an overkill for the moment given many constraints : 1. It is a library, therefore we would just be doing a code testing and lose one of the main advantage of specflow (integration microservice engine) 2. How we would copy the Gherkins over to the project to have it always synchronized is something to be seen (a copy/paste is the likely options) For the moment, nothing stops us from adding more integration tests using the classical approach. The more integration tests we will have, the easier it will be to move over to Specflow. All the best :slightly_smiling_face: (Sorry, I was a bit busy this week and saw the messages only today)

pact544
2021-06-10 13:25
I think the gherkin stuff would have to be in a separate repo (although we could start it in one of the language repos to prove it first then split it out after). We'd probably need either a branch per spec version like the spec repo is, or liberal use of tagging or something. In terms of importing them, you'd either want to download them during CI or something, or have a git submodule

greg595au
2021-06-12 07:30
hi @pact544 that is the gist of my diagram - isolation of the generic spec gherkin from implementation. That would provide high level guidance on specs and allow language differences (to the most part) to be sorted at implemenation time. This does lead to the situation where there will be semantic and specific language requirements. But as a start using positive tests: ? Common Spec Given When Then ? RFC compliance tests Then we start to implement more, as @jacek.helper pointed out, we need to map our test strategy to enable sensible and adoptable testing approach across http://Pact.io

greg595au
2021-06-12 07:31
(PS - i had to replace my good machines HDD - seems its had enough)

pact544
2021-06-12 08:22
I wonder how we actually do it from a practical perspective though. For example, we'd write tests for spec v4 but they'd currently fail for PactNet as it only supports v3. Or we'd write v3 message tests which would currently fail. That means they can't run as part of CI otherwise they'd always fail. Tests that aren't run as part of CI aren't particularly useful, and neither are tests that always fail. I'm really not sure how each language declares the tests that _should_ pass so that they can run in CI and find regressions. It's like each language needs to provide its own set of ignores, but that can't be in the central gherkin repo obviously, so I'm not sure how they do that.

greg595au
2021-06-12 08:56
we have a few choices on managing that angle. Branching, folders or tags

greg595au
2021-06-12 08:56
tags can become unmanagable, branches isolate V3 from V4 specs nicely

greg595au
2021-06-12 08:57
folders are great but then we have a bunch of tests that are not implemented

pact544
2021-06-12 08:57
Branch/tag sounds too cumbersome to me. That would mean you can't update to that branch/tag until you are fully compliant with every test in there. I'm not sure folders works either - how would you tell it to only run certain folders?

greg595au
2021-06-12 08:58
we can force cucumber to filter to folders

pact544
2021-06-12 08:58
I've never done that for SpecFlow before. Are you sure that's possible?

greg595au
2021-06-12 08:58
i am not a fan of folders, but we need to consider all possibilites and narrow down most suitable

greg595au
2021-06-12 09:02
@pact544 like this way

pact544
2021-06-12 09:04
That's only one base folder though. I'm not sure you could organise the folders sufficiently hierarchically that you can opt in and out of tests. Plus that's the CLI runner, which doesn't apply in Visual Studio or `dotnet test`

greg595au
2021-06-12 09:04
and by

pact544
2021-06-12 09:13
So you'd have to do this basically: https://docs.specflow.org/projects/specflow/en/latest/Execution/Executing-Specific-Scenarios.html But there'd have to be so many tags that it would be really awkward to write those filters. They'd end up huge and it would be very tricky to manage them in the central repo for all languages

greg595au
2021-06-12 09:13
have you got a picture in your mind of exactly what we need tag wise?

pact544
2021-06-12 09:17
I've not, but that's kinda the problem I think. In my mind we're going to need a lot of tags because different languages have different levels of support so it's not as simple as just tagging the spec version or whatever. You need to tag the 'sub features' of each spec. Just like how PactNet currently supports v3 but not in full - it doesn't support message pacts and it doesn't support combining multiple matchers in request/response pacts. Those two features would need their own tags so PactNet can ignore them but other languages don't.

greg595au
2021-06-12 09:19
can we have a larger group discussion (maybe teams or other meeting) so we can get a picture of this laid down to inform us how complex this might get

pact544
2021-06-12 09:19
Then your filter is like `v3 & !(message | multipleMatchers | ...)`

greg595au
2021-06-12 09:28
@yann.courtel @jacek.helper @pact544 @uglyog @matt.fellows When is a good time to schedule in a discussion so we can map out folder/branching/tagging/filtering so we can make good engineering decisions about the way forward with the next steps

greg595au
2021-06-12 09:31
@pact544 i concur that we are going to have complexities and possible issues to nut out. Would you be up for a larger team chat to flesh out a map that shows/demonstrates where the issues (and future gotchas) lye.

matt.fellows
2021-06-13 10:24
Tuesday/Thursday nights next week work for me, which would be Monday morning EU

matt.fellows
2021-06-13 10:25
having a rough couple of weeks Greg!

greg595au
2021-06-13 11:43
only the machine

yann.courtel
2021-06-14 09:44
Tuesday works for me for since it's European time, we will have to come up with a specific time? :slightly_smiling_face:

yann.courtel
2021-06-14 09:47
I think @greg595au the first option that comes up in my mind is to not block on the BDD tests. The best approach I see at the moment is to let the languages import the BDD scenarios manually from the repository and add them to their BDD test project. that way we can see which feature is develop for which language. The filtering approach sounds too complex. We can talk about it though next time we meet.

joaoproenca
2021-06-14 10:17
has joined #pact-net-development


greg595au
2021-06-14 10:26
Where Pact Specs are our wiki (by version)

yann.courtel
2021-06-14 10:27
No I have absolutely no problem with your diagram, I'm talking about the actual implementation. How we can achieve that in Specflow and if it's not too complicated at first. The filter / branch approach.

yann.courtel
2021-06-14 10:28
I agree having scenarios in Gherkins could be a great idea to vehiculate the PACT specs but the process of importing them in each language needs to be reviewed thoroughly. We don't want to add unnecessary complexity :)

greg595au
2021-06-14 10:29
One thing that often happens is we see complexity because that is where our minds are.. I think tags might need to be thought of in a more streamlined way. But I will leave that till we convene for a conversation where we can trial the ideas on paper

greg595au
2021-06-14 10:33
My parting thoughts, if we fixate on what can't be done and over look simplifications, we'll be ineffective influencing uptake in other languages as they progress.

yann.courtel
2021-06-14 13:04
I understand your point. Although my thoughts were coming out of researching a way to do it, not just posturing. I see the potential of such a repository.

yann.courtel
2021-06-15 07:51
Hi everyone, I created a branch for the messaging support that is pulled from the feature/4.0.0 branch. https://github.com/pact-foundation/pact-net/tree/feature/messaging-support This will be the main branch to add functionalities for the messaging according to the PACT specs 3.0. I did most of the consumer part and will work on the provider side today. Any feedback will be welcome.

pact544
2021-06-15 08:06
Niiiice. I'll try and take a look at some point

yann.courtel
2021-06-15 09:29
I'm still not convinced about the Consumer verification of the message. It's done by the MessageReify method on the RUST (Verify<T> of the NativeMessageBuilder) that returns an object with a property Contents that has the message without the matchers. There is a double deserialization... therefore I'm not sold on it just yet ^^

yann.courtel
2021-06-15 09:34
Another thing I'm not convinced of is the NativeMockServer that has all the methods for all the interaction model. Including the message support. Maybe we could better separate the Interop methods (class Interop as internal instead of private) and add a NativeHttpMockServer and a NativeMessageMockServer which uses only part of the Interop methods...

yann.courtel
2021-06-15 09:44
Yep, the NativePactMessageBuilder should absolutely NOT have a dependance to IMockServer as it could use the method CreateMockServerForPact and that is not conceivable. I will have a new IMessageMockServer to encapsulate just what we need.

pact544
2021-06-15 09:47
Yeah the class can just implement both interfaces, but pass round as interface to prevent being able to call the wrong one

yann.courtel
2021-06-15 09:48
Yeah right! an IHttpMockServer and IMessageMockServer and each builder will have the right abstraction. Good idea and less changes!

pact544
2021-06-15 09:51
Yeah that's how the v2/v3 builder works. Two separate interfaces so you can't get it wrong, but `NativeMessageBuilder` just implements both to reduce code duplication

yann.courtel
2021-06-15 09:57
Right. I pushed the change. I still have some matchers Unit tests that are failing :confused:

pact544
2021-06-15 09:58
Because of the i18n issues? Yeah they all need to be `JsonConvert.Serialize(testValue)` instead of just a string interpolation, then they'll format correctly

yann.courtel
2021-06-15 09:59
yeah some mistake we had before, I'll look at it at the very end :wink: I'd like to spend some time on the provider side.

pact544
2021-06-15 09:59
Yeah no probs. We should fix that in the release branch instead of this one anyway :thumbsup:

matt.fellows
2021-06-15 11:35
> I'm still not convinced about the Consumer verification of the message. It's done by the MessageReify method on the RUST (Verify<T> of the NativeMessageBuilder) that returns an object with a property Contents that has the message without the matchers. There is a double deserialization... therefore I'm not sold on it just yet ^^

matt.fellows
2021-06-15 11:35
Could you please elaborate on this?

matt.fellows
2021-06-15 11:36
Reify doesn't validate anything, just so we're clear (I think you know this)

matt.fellows
2021-06-15 11:37
If you can easily strip the matchers in .NET you don't need to call reify

matt.fellows
2021-06-15 11:37
But in some ways it's safer, because the object that is returned is what Pact thinks it saw, so there are less chances of error

pact544
2021-06-15 11:43
Yeah using reify is better because stripping matchers is non-trivial (it's all recursive and stuff :joy:). I think Yann's problem is that the reified message appears to be double serialised/escaped so it's difficult to work with

matt.fellows
2021-06-15 11:44
Hmm need to remember the decision there. I needed to be escaped I think because the payload isn't necessarily JSON

matt.fellows
2021-06-15 11:45
Eg. If it's binary it'll be base64 encoded But we can change that if easier

matt.fellows
2021-06-15 11:46
Let me know

yann.courtel
2021-06-15 12:15
Hey @matt.fellows I was referring to the implementation on the branch itself, not the approach :slightly_smiling_face:

yann.courtel
2021-06-15 12:16
I do a reify, get the object, use the content without the matchers and use it to check the consumer handler. The only thing I'm not sure of is the way I deserialize it :wink: mainly implementation details.

matt.fellows
2021-06-15 12:36
Ah cool, carry on then :rolling_on_the_floor_laughing:

yann.courtel
2021-06-21 08:16
Hi guys, a little update on the provider implementation of messaging support. I'm making good progress for the verification process. (was able to verify a PACT message contract with the CLI verifier) I'm adding a middleware in the library that could be easily added to an API that wishes to use the message interaction model as part of their verification pipeline. It follows the approach of having a proxy to check the request going in here (https://github.com/pact-foundation/pact-message-demo) The user would just have to add some kind of message scenario invoker to produce the message based on a named interaction. Some roadblocks I ran into and not sure on how to deal with just yet: ? How to deal with the non existant log on the verification side (this one is painful, I see the rust is only calling the verifier CLI but having zero log for the verification process hurts. Something we have to work on in the 4.0.0 feature branch) ? Adding a net core message middleware will work with certain version of the framework and therefore will be limited (likely net standard 2.0 or greater) Let me know if you have any feedback. Thank you

matt.fellows
2021-06-21 14:01
There are logs, are you not enabling them? Or is this that xunit thing that swallows them?

matt.fellows
2021-06-21 14:02
We have a new log setting to log to different sinks but that may not yet be released

matt.fellows
2021-06-21 14:02
That could mean to could buffer the logs and print, or write to file etx

yann.courtel
2021-06-21 14:05
you are right, there is an init method for the FFI but we don't use it. We just set the log level in the .net lib. I'll look into how to pass the right configuration.

yann.courtel
2021-06-21 14:06
EDIT: actually we do..... mea culpa :smile: I'll focus on finishing the middleware and then I'll look into the log problem haha

matt.fellows
2021-06-22 04:24
haha

matt.fellows
2021-06-22 04:24
I?m going to look at releasing the latest rust libs in the next few days, and get Pact go using them

pact544
2021-06-22 18:52
Hi all - sorry I've been away for a while. I was on vacation and then you know what it's like when you get back :smile: I've just fixed and merged my chore MR about verifying SHA sums of downloaded native libs.

pact544
2021-06-22 18:53
From a bit of local testing, I think we need to change the consumer verification API slightly, which actually brings it more in line with how JS/Go work I think. The current API is like: ```using (IPactContext context = this.pact.Build()) { var client = new EventsApiClient(context.MockServerUri); await client.Invoking(c => c.GetAllEvents()).Should().ThrowAsync<Exception>(); }``` but the problem that I've found is that if the test fails, the `Dispose` method throws on the pact context, and then the inner exception gets swallowed. I think the new API needs to be more like JS/Go with a lambda: ```this.pact.Verify(ctx => { var client = new MyClient(ctx.MockServerUri); await client.FooAsync(); }``` That way if the client call fails then we can surface that exception instead of swallowing it during the dispose What do people think? It's not a difficult change, just something I can do quickly once we're agreed

matt.fellows
2021-06-23 01:52
I wish I didn?t have to do that in JS/Go, because it makes the code a bit more verbose/less readable. But it does have a number of upsides

matt.fellows
2021-06-23 01:55
The other thing I did recently, was to write Pact tests for our terraform provider. Doing so, I made a bunch of little updates to the error output. Each language is going to be different, but I managed to be able to get the line number of the test that was failing and provide a nice little diff ```--- ? Running Pact tests go test -tags=consumer -count=1 -v http://github.com/pactflow/terraform/client/... === RUN TestClientPact --- PASS: TestClientPact (0.00s) === RUN TestTerraformClientPact === RUN TestTerraformClientPact/Pacticipant === RUN TestTerraformClientPact/Pacticipant/CreatePacticipant === RUN TestTerraformClientPact/Pacticipant/ReadPacticipant === RUN TestTerraformClientPact/Pacticipant/UpdatePacticipant === RUN TestTerraformClientPact/Pacticipant/DeletePacticipant === RUN TestTerraformClientPact/Team === RUN TestTerraformClientPact/Team/ReadTeam === RUN TestTerraformClientPact/Team/CreateTeam === RUN TestTerraformClientPact/Team/UpdateTeam === RUN TestTerraformClientPact/Team/DeleteTeam === RUN TestTerraformClientPact/Team/UpdateTeamAssignments === RUN TestTerraformClientPact/Secret === RUN TestTerraformClientPact/Secret/CreateSecret === RUN TestTerraformClientPact/Secret/UpdateSecret === RUN TestTerraformClientPact/Secret/DeleteSecret === RUN TestTerraformClientPact/Role === RUN TestTerraformClientPact/Role/CreateRole === RUN TestTerraformClientPact/Role/ReadRole === RUN TestTerraformClientPact/Role/UpdateRole === RUN TestTerraformClientPact/Role/DeleteRole === RUN TestTerraformClientPact/User === RUN TestTerraformClientPact/User/CreateUser === RUN TestTerraformClientPact/User/ReadUser === RUN TestTerraformClientPact/User/UpdateUser === RUN TestTerraformClientPact/User/DeleteUser === RUN TestTerraformClientPact/User/SetUserRoles === RUN TestTerraformClientPact/Token === RUN TestTerraformClientPact/Token/ReadTokens === RUN TestTerraformClientPact/Token/RegenerateToken === RUN TestTerraformClientPact/Webhook === RUN TestTerraformClientPact/Webhook/CreateWebhook === RUN TestTerraformClientPact/Webhook/ReadWebhook === RUN TestTerraformClientPact/Webhook/UpdateWebhook === RUN TestTerraformClientPact/Webhook/DeleteWebhook === RUN TestTerraformClientPact/Webhook/AuthenticationSettings === RUN TestTerraformClientPact/Webhook/AuthenticationSettings/SetTenantAuthenticationSettings === RUN TestTerraformClientPact/Webhook/AuthenticationSettings/ReadTenantAuthenticationSettings client_pact_test.go:932: Pact Verification Failed for: TestTerraformClientPact/Webhook/AuthenticationSettings/ReadTenantAuthenticationSettings Diff: actual: GET /admin/tenant/authentication-settings (Unexpected request was received) expected: GET /dmin/tenant/authentication-settings (Expected request that was not received) client_pact_test.go:942: Error Trace: client_pact_test.go:942 Error: Received unexpected error: system unavailable please see the log for error details Test: TestTerraformClientPact/Webhook/AuthenticationSettings/ReadTenantAuthenticationSettings --- FAIL: TestTerraformClientPact (0.10s) --- PASS: TestTerraformClientPact/Pacticipant (0.02s) --- PASS: TestTerraformClientPact/Pacticipant/CreatePacticipant (0.01s) --- PASS: TestTerraformClientPact/Pacticipant/ReadPacticipant (0.00s) --- PASS: TestTerraformClientPact/Pacticipant/UpdatePacticipant (0.00s) --- PASS: TestTerraformClientPact/Pacticipant/DeletePacticipant (0.00s) --- PASS: TestTerraformClientPact/Team (0.02s) --- PASS: TestTerraformClientPact/Team/ReadTeam (0.00s) --- PASS: TestTerraformClientPact/Team/CreateTeam (0.00s) --- PASS: TestTerraformClientPact/Team/UpdateTeam (0.00s) --- PASS: TestTerraformClientPact/Team/DeleteTeam (0.00s) --- PASS: TestTerraformClientPact/Team/UpdateTeamAssignments (0.00s) --- PASS: TestTerraformClientPact/Secret (0.01s) --- PASS: TestTerraformClientPact/Secret/CreateSecret (0.00s) --- PASS: TestTerraformClientPact/Secret/UpdateSecret (0.00s) --- PASS: TestTerraformClientPact/Secret/DeleteSecret (0.00s) --- PASS: TestTerraformClientPact/Role (0.01s) --- PASS: TestTerraformClientPact/Role/CreateRole (0.00s) --- PASS: TestTerraformClientPact/Role/ReadRole (0.00s) --- PASS: TestTerraformClientPact/Role/UpdateRole (0.00s) --- PASS: TestTerraformClientPact/Role/DeleteRole (0.00s) --- PASS: TestTerraformClientPact/User (0.02s) --- PASS: TestTerraformClientPact/User/CreateUser (0.00s) --- PASS: TestTerraformClientPact/User/ReadUser (0.00s) --- PASS: TestTerraformClientPact/User/UpdateUser (0.00s) --- PASS: TestTerraformClientPact/User/DeleteUser (0.00s) --- PASS: TestTerraformClientPact/User/SetUserRoles (0.00s) --- PASS: TestTerraformClientPact/Token (0.01s) --- PASS: TestTerraformClientPact/Token/ReadTokens (0.00s) --- PASS: TestTerraformClientPact/Token/RegenerateToken (0.00s) --- FAIL: TestTerraformClientPact/Webhook (0.02s) --- PASS: TestTerraformClientPact/Webhook/CreateWebhook (0.00s) --- PASS: TestTerraformClientPact/Webhook/ReadWebhook (0.00s) --- PASS: TestTerraformClientPact/Webhook/UpdateWebhook (0.00s) --- PASS: TestTerraformClientPact/Webhook/DeleteWebhook (0.00s) --- FAIL: TestTerraformClientPact/Webhook/AuthenticationSettings (0.00s) --- PASS: TestTerraformClientPact/Webhook/AuthenticationSettings/SetTenantAuthenticationSettings (0.00s) --- FAIL: TestTerraformClientPact/Webhook/AuthenticationSettings/ReadTenantAuthenticationSettings (0.00s) FAIL FAIL http://github.com/pactflow/terraform/client 0.273s FAIL make: *** [pact] Error 1 ? terraform git:(master) ?```

matt.fellows
2021-06-23 01:56
In my case, having it in a closure made that a bit easier

yann.courtel
2021-06-23 08:35
It's actually a good idea. I was eluded to that when I was referring to hiding the pact.Build() method a while back. It's a much more elegant way to write it as well forcing the client to use the pact instead of a code snippet. Footnote: The messaging will work the same way by the way.

yann.courtel
2021-06-24 07:08
Hi everyone, I pushed my latest changes in the https://github.com/pact-foundation/pact-net/tree/feature/messaging-support branch. Provider verification for messaging is available in the branch. Messaging support works with dynamic messages when you set up your scenario using a scenario builder. See sample app here: https://github.com/pact-foundation/pact-net/tree/feature/messaging-support/samples/EventImporter/Provider.Tests The point is to setup a simulated message that will come from your API rather than pushed in the queue and compare it to the message in the contract interaction. The functional key would be the interaction description. Let me know what do you think about this implementation.

yann.courtel
2021-06-24 07:14
If you check the MessageMiddleware, you can see where the message is actually invoke and set in the http response: https://github.com/pact-foundation/pact-net/blob/feature/messaging-support/src/PactNet.Native/Messaging/MessageMiddleware.cs

yann.courtel
2021-06-24 14:59
All the unit tests have been fixed and the CI is working. I just need to finalize the unit tests and it will be all good :sweat_smile:

pact544
2021-06-26 19:16
So examples of the new API with a `Verify`/`VerifyAsync` method for consumer interaction verification, as mentioned: ```this.pact .UponReceiving("a request to retrieve all events") .Given("there are events with ids '45D80D13-D5A2-48D7-8353-CBB4C0EAABF5', '83F9262F-28F1-4703-AB1A-8CFD9E8249C9' and '3E83A96B-2A0C-49B1-9959-26DF23F83AEB'") .WithRequest(HttpMethod.Get, "/events") .WithHeader("Accept", "application/json") .WithHeader("Authorization", $"Bearer {Token}") .WillRespond() .WithStatus(HttpStatusCode.OK) .WithHeader("Content-Type", "application/json; charset=utf-8") .WithJsonBody(expected); // async version await this.pact.VerifyAsync(async ctx => { var client = new EventsApiClient(ctx.MockServerUri, Token); IEnumerable<Event> events = await client.GetAllEvents(); events.Should().BeEquivalentTo(expected); }); // sync version this.pact.Verify(ctx => { var client = new EventsApiClient(ctx.MockServerUri, Token); IEnumerable<Event> events = client.GetAllEvents(); events.Should().BeEquivalentTo(expected); });``` That's needed because the previous API with an `IDisposable` meant that if the interaction itself threw an exception, that exception would be swallowed silently because the exception from the `Dispose` would be thrown instead.

pact544
2021-06-26 19:17
The `ctx` arg to the lambda is of type `IConsumerCOntext` and currently only contains the mock server URI so that you can use it when constructing your client. The reason I did that instead of just passing the URI itself is so that we wouldn't need a breaking change in future if we ever wanted to pass additional arguments.


yann.courtel
2021-06-28 12:03
Hey @pact544 This is perfectly understandable from the consumer side.

yann.courtel
2021-06-28 12:23
I finished your review. Just a few comments :slightly_smiling_face:

pact544
2021-06-28 12:23
Cool, I'll check it out, thanks!

yann.courtel
2021-06-28 12:40
I forgot about the Invoking (FluentAssertions). It's SOOO handy

tjones
2021-06-28 12:42
Nice work, @pact544! Looks like a good quality-of-life improvement for users

tjones
2021-06-29 11:43
Friends, I?ve made a start (locally) on a ?pact features? document, to record the things that are in each implementation. It?s quite small so far: ```$ cat pact-features.md ## Messages Provider Verification Provider verification with metadata Consumer Tests Consumer tests with matchers Consumer tests with metadata```

tjones
2021-06-29 11:44
but, while going through the V3 upgrade it seems like a good time to take note of what is in a Pact implementation

tjones
2021-06-29 11:44
We don?t really have anything that tracks the different status of features in each framework



pact544
2021-06-29 19:16
I've merged the changes to the consumer tests API, thanks for reviews @yann.courtel and @tjones :thumbsup:

matt.fellows
2021-06-30 03:52
Greg - Tim is also based in Australia. Perhaps we can organise a call in the next few weeks to chat about this?

matt.fellows
2021-06-30 03:53
I just spoke to Tim, and we both think it would be a great addition to have documented. Even if we don?t yet implement (via tests), having the behaviour documented would be a really great start

yann.courtel
2021-06-30 07:27
Thank you! I'll have the change onto my dev branch and hopefully I will have time today to do a PR also.

yann.courtel
2021-07-01 15:06
Hi everyone, I created a draft pull request for the messaging support : https://github.com/pact-foundation/pact-net/pull/309 Can you have a look and see if anything jumps out? Let me know also if something is not clear. A couple of things might be left to do is to work on a middleware that is compatible with .net core app 1.0 and .net framework 4.6. Right now the provider middleware for messaging is only compatible with netstandard2.0+ Another will be to run the tests with a netcoreapp1.0 framework. I haven't had time to work on that. Thank you.

yann.courtel
2021-07-02 08:00
Hi everyone ! Question regarding a method of the FFI @matt.fellows and @uglyog What is this method actually for ? It seems to allow the writing of metadata from the message pact handle. We do have then the normal message interaction metadata and the pact metadata where the pact specs and rust version are, is that correct ?

matt.fellows
2021-07-02 11:59
yeah. This is for adding extra data into the pact file

matt.fellows
2021-07-02 12:01
My initial thoughts were to add the details of the client library

matt.fellows
2021-07-02 12:02
e.g. perhaps `pactNet.version` would be good to have in there?

matt.fellows
2021-07-02 12:02
The metadata can be displayed into the pact broker, to help with bug diagnosis etc.

yann.courtel
2021-07-02 14:02
We actually initiate a PactV3 or in the Future PactV4 that will set the specifications automatically (with the WithSpecifications). So I think that would be redundant. I'll try adding another version just to see if it works though :)

matt.fellows
2021-07-02 23:32
It's not the spec version, it's the version of Pact .NET we'd put in there

matt.fellows
2021-07-02 23:32
The spec version is automatically added there by rust

matt.fellows
2021-07-02 23:33
We discussed also using it for feature flags(potentially language specific) and similar things

uglyog
2021-07-03 02:06
Here is what Pact-JVM puts in there: ```"metadata": { "pact-jvm": { "version": "4.2.8" }, "pactSpecification": { "version": "3.0.0" } }``` and Pact-JS V3 ```"metadata": { "pactJs": { "version": "10.0.0-beta.33" }, "pactRust": { "version": "0.8.11" }, "pactSpecification": { "version": "3.0.0" } }```

uglyog
2021-07-03 02:09
We can then show this info in UI (this is from Pactflow)

pact544
2021-07-04 20:50
I've done a rather large (sorry :smile:) review of the message pact branch :thumbsup: Hopefully it's not too harsh! I think we need to change the API somewhat though in order to maintain consistency with the request/response pacts, and to use the type-state pattern so the user falls into the pit of success instead of allowing them to potentially make mistakes and us validate their actions afterwards. I think we also need to revert any 'cosmetic' changes to make the diff easier to read (like removing `this.` or adding spaces in `using` declarations at the top). I very nearly missed some new code in the middle of a bunch of those cosmetic changes. We should generally agree a convention and stick with it so it's easier to navigate the codebase as a whole anyway I think. And obviously I think my preferences should be the default because I went first :stuck_out_tongue_closed_eyes::joy:

greg595au
2021-07-05 03:16
adam, you're very cheeky. I suspect that Matt prefers we adopt the C# recommendations, which means the project never adopted some practices early on and now we have some cosmetic chagnes - but your right, they have cleverly masked other changes

yann.courtel
2021-07-05 07:25
Thank you very much for the large review! I agree with the leading the user to the path of success typing there request and managing invariants but how would you achieve that? I agree with everything except the "And obviously I think my preferences should be the default because I went first" ^^ These cosmetic changes are resharper default considerations for most and I think we should stick to that and avoid any unnecessary code. (except the spacing in the using, I can revert that) What I can agree with is to do it in another PR so we don't crowd this one. Therefore, we can talk about it later and decide and how we configure our IDE. I'm going through all the changes so some answers will come through the PR :slightly_smiling_face: thanks again

yann.courtel
2021-07-05 07:26
Thanks @uglyog in .net, we actually append the rust version as well which is very useful.

matt.fellows
2021-07-05 07:40
> I agree with everything except the ?And obviously I think my preferences should be the default because I went first? ^^ :laughing:

matt.fellows
2021-07-05 07:40
I like that Greg suggested I had opinions here (I do, but not the ones you?re expecting probably)

matt.fellows
2021-07-05 07:41
My suggestion is to get the rules identified now, because once it?s merge into mainline, cosmetic refactors are a pain in the butt for git-blame etc. - e.g. now the last person who changed it didn?t really change it, they just made it pretty

pact544
2021-07-05 07:43
> Thank you very much for the large review! I agree with the leading the user to the path of success typing there request and managing invariants but how would you achieve that? If you separate out the "things you can do to an interaction" into a separate interface, and the "start a new interaction" method return the first interface, then you are forced to start a new interaction before you can configure it. That means you don't need to validate "trying to configure an interaction before you've actually started it"

pact544
2021-07-05 07:45
So for the request/response style it's `IPactBuilder.UponReceiving` which returns `IRequestBuilder`, which has all the `WithPath`, `WithQuery` etc. That means you never need to validate that `WithQuery` isn't called before `UponReceiving`, because it's literally impossible to do that

pact544
2021-07-05 07:46
So if you did like `IPactBuilder.ExpectsToReceive` which returns `IMessageBuilder` (or whatever it's called) then you can't get it wrong

yann.courtel
2021-07-05 08:07
Okay, so sticking with different level builders to avoid any invariant. I can prob do like that. The problem will come when we want to call the build method after the verify since it's another builder. I could always reference the parent builder in the sub-builder and see how it looks.

yann.courtel
2021-07-05 08:11
@greg595au @matt.fellows Agree with the conventions. The questions is which conventions? :smile: There are may out there => we could use the microsoft ones https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines Or we could adapt certain conventions to match our IDE... What @pact544 was suggesting mainly (I think so ^^) was not to mix it with the messaging, that way, we can apply the new conventions in the feature/4.0.0 branch later on. We should start a different thread to talk about it.


yann.courtel
2021-07-05 09:20
@greg595au that is the second sublink to the link I copied :slightly_smiling_face: since it's not just coding conventions but also namespace and so on.

yann.courtel
2021-07-06 09:51
Hey everyone :slightly_smiling_face: I looked at all the remarks you've sent @pact544. Some work to do which I will be doing mostly tomorrow. Some points I'm not 100% sure of yet but for most I can fix. Thank you again for the review.

matt.fellows
2021-07-06 10:00
:taco: :taco: for @yann.courtel

matt.fellows
2021-07-06 10:00
:taco: for @pact544

matt.fellows
2021-07-06 10:00
This is great

matt.fellows
2021-07-06 10:00
I have the code open now, and don?t know where to begin - so much stuff!

matt.fellows
2021-07-06 10:10
@pact544 saw this, and agree. It? seems strange to me that that?s not a thing.


matt.fellows
2021-07-06 10:11
See also https://github.com/pact-foundation/pact-reference/pull/119. There is a new method to log into core, and another to initialise with the log level directly (rather than needing an env var to set it).

matt.fellows
2021-07-06 10:11
But it doesn?t allow you to change it after init

pact544
2021-07-06 15:19
Yeah we'd need a static property on PactNet that you can set, and you'd have to set it before you did any work with the library at all (and probably throw an exception if someone does try to do that). We should raise it as a ticket to use the new core logging method :+1: Shouldn't be difficult once it's in an official pact-rs release

yann.courtel
2021-07-07 07:21
Always start by the tests :wink: the integration one, on the sample projects will give you a good idea.

yann.courtel
2021-07-09 15:16
Hi everyone, sorry for the delay on the messaging, I had one of those weeks... I'll be back next Thursday to try to push the branch for end of next week! Enjoy your weekend.

matt.fellows
2021-07-13 11:32
cc: @elliottmurray

elliottmurray
2021-07-13 11:34
has joined #pact-net-development

matt.fellows
2021-07-18 11:33
:wave: hey folks, just wanted to check-in to see how things have been traveling?

matt.fellows
2021-07-18 11:34
There?s been lots of activity in the code, which can be overwhelming for a http://non-.NET person - but do reach out if there are spots that we can help guide etc.

matt.fellows
2021-07-18 11:35
Related to this, we?ll probably have the next Pactflow POST go out in the next week or two. It?s likely we?ll include Pact Go?s support for v3 has moved to beta to help drive some adoption.

matt.fellows
2021-07-18 11:36
I?m not sure if it makes sense to mention .NET just yet, I don?t believe it?s currently distributed to Nuget right? If you need any help with that, reach out as I do currently have access. But I know DiUS (my employer) is doing some work with a .NET client at the moment, and I?d love to get this in their hands to take it for a spin.

pact544
2021-07-20 18:19
I was kinda waiting until the new combined FFI came out and then perhaps update the 4.0 branch to start using that instead. We're still a decent way from beta I think just because the logging support is behind where it used to be with the Ruby integration. In particular the verifier logging is lagging some way behind I think. Other than that it's all the documentation and stuff that goes round it that all needs updating, and should be good to go.

matt.fellows
2021-07-20 23:26
The new FFI is out, ICYMI


matt.fellows
2021-07-20 23:26
I?ll probably take a look at it today for Pact Go, just to wrap my head around it

matt.fellows
2021-07-30 02:46
@erik.moller the v4 branch is currently here: https://github.com/pact-foundation/pact-net/tree/feature/4.0.0

yann.courtel
2021-08-10 08:55
Hey @pact544. Back from vacation :slightly_smiling_face: I saw your changes for the logging. I will check that out on the messaging branch right away.

yann.courtel
2021-08-10 09:25
I looked at your PR and it looks okay. Can we merge it and see if it works in the 4.0.0 branch? I'd like to verify it to the messaging branch. Thanks

pact544
2021-08-10 15:53
Yeah we can merge if it works :+1: I've also been away for quite a long time so not sure if there's an updated core library with unified logging yet.

pact544
2021-08-10 18:46
I'm making a start on moving the FFI over to the new combined FFI now. Wish me luck!

pact544
2021-08-10 18:53
OK it's quite a bit different. This isn't going to be a quick one!

pact544
2021-08-10 19:03
Argh, the file name structure has changed again (so Linux and OSX are called `libpact` whereas Windows is just called `pact` ). I think that breaks the download script :disappointed:

matt.fellows
2021-08-10 22:36
> OK it?s quite a bit different. This isn?t going to be a quick one! I think the main difference is that they have prefixes (that discussion was ? _somewhere_)

matt.fellows
2021-08-10 22:37
But the name difference seems wrong

uglyog
2021-08-10 23:11
We can easily change that

pact544
2021-08-11 17:45
Yeah sorry, I immediately jumped into the new iterators bit for verification failures and thought the old way had gone, but since found it.

pact544
2021-08-11 17:46
The name difference for the OSX library actually doesn't seem to matter - the tests pass on CI anyway

yann.courtel
2021-08-12 07:11
I approved it, go for merge.

matt.fellows
2021-08-12 07:15
@pact544 @yann.courtel FYI @edanielsen has just updated https://github.com/DiUS/pact-workshop-dotnet-core-v2 based on your branch! Very cool (we have pushed a build to a public artifactory so it can work). I?ve yet to look at it, but just know that people are champing at the bit. Also as you might have seen, the feedback for the new API has been :mwah:

yann.courtel
2021-08-12 07:17
Thanks a lot. That's a very nice repo here!

matt.fellows
2021-08-12 07:18
(for reference, it?s based off the previous workshop)

pact544
2021-08-12 16:03
Oh nice :+1: yeah once we've got nice logging for both consumer and provider sides I think it's worth releasing a beta. Messaging support can be added soon after that I think, but nice to get the core stuff out.

yann.courtel
2021-08-13 08:46
I had a similar repository for our lib encapsulating pact-net. The good thing is to put different levels including as @pact544 pointed it out, an exercice with different interaction model such as messaging.

yann.courtel
2021-08-13 08:47
It can also serve as an integrated environment / solution to troubleshoot any issue we might have (related to how many tests on many classes we have)

matt.fellows
2021-08-13 10:01
exactly!

matt.fellows
2021-08-13 10:01
good idea

yann.courtel
2021-08-23 13:07
Hi everyone, A PR to merge the consumer part of the messaging : https://github.com/pact-foundation/pact-net/pull/315 A lot of structural changes made it difficult to rebase so I split the consumer and provider part to be easier to review. There should be minimal changes since it has been reviewed in the other PR here: https://github.com/pact-foundation/pact-net/pull/309 Thank you for your feedback.

yann.courtel
2021-08-23 13:08
We have a 100% Unit Tests cover on the new code. After the messaging, I will make a pass on the Unit and Integration Tests to achieve 100% overall coverage. Thanks

matt.fellows
2021-08-24 01:04
awesome work team

yann.courtel
2021-08-26 08:31
Hi everyone, hope all is well. I think it may be time to have 'the talk'. Yes, I'm talking about *coding and naming conventions* going forward :slightly_smiling_face: For this, I'm thinking of making *a poll* with the different approach we could take. I have many sources (online and first hand) that don't necessarily agree on which conventions are the best... Microsoft : https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions DoFactory : https://www.dofactory.com/csharp-coding-standards (to cite just a few) I'll post it as soon as I have it. Thanks

yann.courtel
2021-08-26 09:36
I addressed all of your comments @pact544 For the sample app, we will find later an example with many messages. Maybe on a later PR. With one message for each message PACT, the metadata do appear! Might be a bug. For the verifying the metadata on the consumer side comment, I don't know how you would do that...

matt.fellows
2021-08-26 09:43
Can't verify metadata on the consumer side, at least the others don't do it that I'm aware of

yann.courtel
2021-08-26 09:48
and actually it doesn't make sense when you think about it from a pact perspective. They are all going to be different from the type of messaging queue you are using. But one thing is for sure is that if your object has a different structure, your consumer should rightfully break. In other words, you can switch the type of queue but if you have the same structure of the object, the pact should work.

edanielsen
2021-08-26 11:03
has joined #pact-net-development

edanielsen
2021-08-26 11:15
Hi guys, I might not be a major contributor going forward (though you never know), but I happen to be helping a client introducing pact at the moment (I work for DiUS, like some of the other folks here), and they happen to use .Net core mostly so when I find a missing feature I might just look at implementing it :smile: I'll see if I can pitch in with some documentation help as well since I had to do some of that while putting together a dotnet workshop modelled on the JS one. Awesome work on the 4.0.0 branch by the way, if it wasn't for that I don't think I would have gotten anywhere with http://Pact.Net

edanielsen
2021-08-26 11:17
I should probably also say that I'm not a .Net developer (far from it), in fact I've never used it before, but I found it quite intuitive coming from a Java background. Still, if you see me doing something weird it's probably because I don't know better

matt.fellows
2021-08-26 11:35
I reckon they would have guessed, given the swift feedback that come through on that PR :slightly_smiling_face:

yann.courtel
2021-08-27 08:55
Awesome! Welcome (officially)! Don't worry Java developers tend to be pretty good at organizing their code base when they switch to C# from my modest experience. Good to have you.

edanielsen
2021-09-01 07:13
While filling in the missing bits in the workshop (https://github.com/DiUS/pact-workshop-dotnet-core-v3) after the header matching has been merged I came across this open issue when wanting to convert the `request filtering` functionality from the JS workshop (https://github.com/pact-foundation/pact-workshop-js/tree/step10#:~:text=step%2010%3A%20request%20filters): https://github.com/pact-foundation/pact-net/issues/216 Is there still no plan to support request filtering within the framework? If not I can show an example in the workshop using middleware as an alternative

matt.fellows
2021-09-01 08:46
Should be much easier to support now the provider state handler code is there

edanielsen
2021-09-01 11:41
Now doing this for the workshop as an example, please let me know if anyone has a better idea: ```using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; namespace tests.Middleware { public class AuthTokenRequestFilter { private const string AuthorizationHeaderKey = "Authorization"; private readonly RequestDelegate _next; public AuthTokenRequestFilter(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (context.Request.Headers.ContainsKey(AuthorizationHeaderKey)) { context.Request.Headers.Remove(AuthorizationHeaderKey); context.Request.Headers.Add(AuthorizationHeaderKey, HeaderValue()); } await this._next(context); } private StringValues HeaderValue() { return $"Bearer {DateTime.Now:yyyy-MM-ddTHH:mm:ss.fffZ}"; } } }```

edanielsen
2021-09-01 11:42
Never mind the token value, it's not built for security :smile:

yann.courtel
2021-09-01 11:55
It's pretty good! I believe we have this one in the sample provider application. I'll see if we can put it in its own project with the provider states middleware.

matt.fellows
2021-09-01 11:57
Are you familiar with the idea of request filters in other languages?


yann.courtel
2021-09-01 12:00
Typically an ActionFilter will run some code before the actual code mapped to the request is done... Used for logging, security or any cross-concern algorithm. Is that what you meant?

matt.fellows
2021-09-01 12:01
pretty similar, but more ?pact? specific


matt.fellows
2021-09-01 12:01
Java has it also

matt.fellows
2021-09-01 12:01
basically, it lets you manipulate the req/res during verification (rather than having to create a separate middleware and configure it onto your application)

matt.fellows
2021-09-01 12:01
under the hood, i?ve implemented it as middleware anyway because in JS/Go that?s super easy.

matt.fellows
2021-09-01 12:02
I assume it?s possible in .NET, but there would need to be other infra there to support it. I?m assuming your provider states handler does some similar magic (e.g. running a proxy behind the scenes)?

yann.courtel
2021-09-01 12:03
yeah, middleware and custom filter attribute address similar issues but on different level of the workflow. The provider state middleware in the sample app does all the magic, that's true ^^

edanielsen
2021-09-01 12:03
Didn't want to derail the chat there but @yann.courtel said `I'll see if we can put it in its own project with the provider states middleware.` Does this mean that the provider state middleware will be embedded into the http://Pact.Net library? If so that's a win. One of the comments I got from the client I used the 4.0.0 branch with was that it felt like a lot of boilerplate having to include that kind of code as part of the test implementation

matt.fellows
2021-09-01 12:04
> Does this mean that the provider state middleware will be embedded into the http://Pact.Net library? If so that?s a win. That actually is not a terrible idea. Does that imply though that all web frameworks use the same underlying APIs or does that only service certain users that use certain frameworks?

edanielsen
2021-09-01 12:05
e.g. having a base class that can be extended to implement the actual state setup and avoid the request path checking bit would be good

yann.courtel
2021-09-01 12:05
We actually spoke during a PR about the messaging with @pact544 to have the messaging middleware (the component used to simulate messages) in its own project. But nothing stops us from adding other middleware, pact related, such as the provider state middleware used by the provider sample app.

yann.courtel
2021-09-01 12:06
That will be a challenge... because middleware definitions are not the same based on the framework version... I need to see how it goes with the messaging middleware and will let you know.

edanielsen
2021-09-01 12:06
Any code that has to be written every time, if it can be provided as part of the library, will increase uptake of http://Pact.Net I think. Makes it look cleaner and simpler

matt.fellows
2021-09-01 12:08
I think I understand now, I must have misinterpreted the example code I saw

pact544
2021-09-01 12:08
Yeah it'd have to be a totally separate package because it depends on the web framework used, and we can't dictate that to users

edanielsen
2021-09-01 12:09
Also @matt.fellows I forgot to show how it's wired in: ``` public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseMiddleware<ProviderStateMiddleware>(); app.UseMiddleware<AuthTokenRequestFilter>(); _proxy.Configure(app, env); }```

edanielsen
2021-09-01 12:09
So it's injected into the request handling pipeline

edanielsen
2021-09-01 12:09
This is for the test app, the actual app under test is the `_proxy`

pact544
2021-09-01 12:09
You'd have to have like a PactNet.AspNetCore with the middleware and some extension methods for registering it

edanielsen
2021-09-01 12:10
which is badly named, it should be the other way around :smile:

edanielsen
2021-09-01 12:11
Ok, this is where I'm far from a .Net expert

edanielsen
2021-09-01 12:12
Makes sense @pact544, these are optional extras depending on your environment

pact544
2021-09-01 12:14
It's a harder problem than it seems on the face of it as well - like what if you want your provider state handler to create some classes (e.g. use your data source class to insert some db data). Now you need to worry about things like dependency injection frameworks as well

edanielsen
2021-09-01 12:15
Doesn't sound like an MVP feature then

yann.courtel
2021-09-01 12:29
With an extensions method to simplify the registering :)

yann.courtel
2021-09-20 15:42
Hi everyone! Sorry for having so little bandwidth the last few weeks. It has been very hectic to be able to work more than one hour at once. I'm having a very last problem before sending a PR for the messaging provider. Everything is fine when I verify the messaging consumer contract in debug with the CLI command (using the ffi from the pact-reference repo). But everything breaks when I do it with the code. The command arguments are the same, the contract is the same, the middleware is the same and the scenario invocation is the same. Is there something that can be drastically different between the CLI and the code integration? ... I'm pretty stuck. Thanks a lot.

matt.fellows
2021-09-21 01:34
Strange

matt.fellows
2021-09-21 01:34
are you newline delimiting each argument (and value)?

matt.fellows
2021-09-21 01:35
Any logs you can share would also be great

tjones
2021-09-21 03:13
Which methods are you using from the code?

yann.courtel
2021-09-21 08:05
The arguments are the same, I don't think it's the formatting. I checked what was sent to the CLI. Plus it's a verification problem. I have two options: 1) the middleware somehow is not registered the same way in my test sample project 2) the change from newtonsoft to system.text.json triggers an underlying error

tjones
2021-09-21 11:32
You could try the verifier from pact-js to see if it's the FFI or python?

tjones
2021-09-21 11:37
We use `pactffi_verify` in v0.0.1 of libpact_ffi

yann.courtel
2021-09-21 12:35
I guess I could try that. Thx

tjones
2021-09-21 14:31
It's in beta, so you'd need `v10.0.0-beta.45` or later. Let me know if you want a hand setting it up

yann.courtel
2021-09-21 16:01
I narrowed it down to one thing. The ffi dll is just not behaving the same way as the CLI... I don't see any other explanation...

tjones
2021-09-22 07:54
Are they built from different versions of the source?

yann.courtel
2021-09-22 08:05
I don't think so. I will push what I have and hope we could sort out the verifier console issue because without the exact error, it's very hard to debug.

matt.fellows
2021-09-22 08:05
Is there a log or error you?re getting? Or just a crash?

matt.fellows
2021-09-22 08:06
If you can share what your code sends, I could try and eyeball

yann.courtel
2021-09-22 08:06
we currently have just an error code saying it's a verification problem. The same issue we've talked about with Adam regarding the verifier console not being caught by the program

matt.fellows
2021-09-22 08:07
can you run from the console then so we get it?

matt.fellows
2021-09-22 08:07
that issue is only present when run from an IDE

yann.courtel
2021-09-22 08:07
correct, I haven't tried with the latest version. Let me see

matt.fellows
2021-09-22 08:08
I don?t think the latest verifier will fix that

matt.fellows
2021-09-22 08:08
I?m asking if you can run the test from your terminal so that we can see the logs/output

yann.courtel
2021-09-22 08:11
I was referring to the latest version of my code. I have tried running dotnet test before. Here is the console that runs the dll

yann.courtel
2021-09-22 08:12
(sorry for the French... my machine has to be in Fr)

matt.fellows
2021-09-22 08:13
hmm i?d expect to see the output from the verifier - do you ever get verifier output from the terminal?

yann.courtel
2021-09-22 08:14
nope, that's an issue

matt.fellows
2021-09-22 08:14
that

matt.fellows
2021-09-22 08:14
should definitely work

yann.courtel
2021-09-22 08:14
And this is the CLI command (the same as in the code)

matt.fellows
2021-09-22 08:14
when I run this workshop locally (via terminal) I definitely see verifier output: https://github.com/DiUS/pact-workshop-dotnet-core-v3/blob/master/Provider/tests/ProductTest.cs#L35

yann.courtel
2021-09-22 08:14
Verification is good

matt.fellows
2021-09-22 08:15
well, that?s a positive!!

yann.courtel
2021-09-22 08:15
I know, at least there is that

yann.courtel
2021-09-22 08:15
ok, true, I'm going to try to tweak it the way Erik did

matt.fellows
2021-09-22 08:16
ok, I assumed that did help?somehow

yann.courtel
2021-09-22 08:16
the xunit output is well configured

matt.fellows
2021-09-22 08:16
my first inclination is that spaces are the problem

yann.courtel
2021-09-22 08:16
something must be obviously wrong with the way it's set up in the test :slightly_smiling_face: that would be a relief

yann.courtel
2021-09-22 08:16
hm... the spaces in the command?

matt.fellows
2021-09-22 08:17
no, the arguments

matt.fellows
2021-09-22 08:17
e.g. ?Event API Consumer V3?

matt.fellows
2021-09-22 08:17
without output visibility, it?s just a guess

yann.courtel
2021-09-22 08:17
ah! yep I thought so...

matt.fellows
2021-09-22 08:18
but an educated one. spaces, special characters etc. are often problematic

yann.courtel
2021-09-22 08:18
but it's not that, the other sample API works and has spacing and uses the same verifier class

yann.courtel
2021-09-22 08:18
the http one

yann.courtel
2021-09-22 08:19
and it doesn't seem to be the json serialisation, I double checked

yann.courtel
2021-09-22 08:19
but you are helping :slightly_smiling_face:

matt.fellows
2021-09-22 08:20
:disappointed:

matt.fellows
2021-09-22 08:20
So, do you know if the verifier starts communicating to your framework? Or does it fail before invoking your verification code?

yann.courtel
2021-09-22 08:22
:open_mouth:

yann.courtel
2021-09-22 08:22
break through... I tried with the old pact json file on my other branch and it works!

matt.fellows
2021-09-22 08:22
hah

matt.fellows
2021-09-22 08:22
I have to go get dinner on for kids etc., but if you wanted to pop the before/after JSON can take a look

yann.courtel
2021-09-22 08:22
it's either a metadata problem, the rust version or the matchers...

yann.courtel
2021-09-22 08:23
no I can look. Thanks a lot! That helped

yann.courtel
2021-09-22 08:23
enjoy your dinner :slightly_smiling_face:

yann.courtel
2021-09-22 08:23
I'll keep you updated and try to push something today

yann.courtel
2021-09-22 08:23
Thank you again

matt.fellows
2021-09-22 08:27
you?re welcome!

yann.courtel
2021-09-22 08:27
it's the metadata... in one pact, there was metadata, in the other not... but why the CLI didn't catch it... very strange

matt.fellows
2021-09-22 08:36
:man-shrugging:

matt.fellows
2021-09-22 08:36
is it the absence or presence of metadata causing issues ?

yann.courtel
2021-09-22 08:37
the presence

matt.fellows
2021-09-22 08:37
ah, which metadata - message metadata or pact file metadata? :laughing:

yann.courtel
2021-09-22 08:38
but that makes sense, at the moment I push an object by the messaging middleware and to be able to put metadata, I need to think in where to put it ^^

yann.courtel
2021-09-22 08:38
message metadata

yann.courtel
2021-09-22 08:42
well! A new thing to figure out!

yann.courtel
2021-09-22 09:15
I found this snippet in the FFI project. Can someone explain to me please how the metadata is actually extracted? I see it's getting something from the header of the request but I must not have the good formatting. Trying to force to add header info until it works. Any thought @uglyog? Thanks a lot

tjones
2021-09-22 09:25
Ah right, there's some docs on this somewhere

yann.courtel
2021-09-22 09:27
For now, it seems doing something along these lines might be the answer. Formatting is not right though

tjones
2021-09-22 09:27
``` // Invoke the handler, and return the JSON response body // wrapped in a Message this.setupStates(message) .then(() => this.findHandler(message)) .then((handler) => handler(message)) .then((messageFromHandler) => { if (hasMetadata(messageFromHandler)) { const metadata = encodeBase64( JSON.stringify(messageFromHandler.__pactMessageMetadata) ); res.header('Pact-Message-Metadata', metadata); res.header('PACT_MESSAGE_METADATA', metadata); return res.json(messageFromHandler.message); } return res.json(messageFromHandler); })```

tjones
2021-09-22 09:27
This is what we do. I can't remember where it's documented, sorry.

tjones
2021-09-22 09:28
`Pact-Message-Metadata` <-- you only need this header, the capital one is from an older version

yann.courtel
2021-09-22 09:28
that's exactly that

yann.courtel
2021-09-22 09:28
but I believe it doesn't matter since it compares after doing a to_lower_case

yann.courtel
2021-09-22 09:28
but serializing a dynamic object might work! let me try

tjones
2021-09-22 09:28
it does, because `_` and `-`

tjones
2021-09-22 09:29
I don't speak .NET very well any more, but it looks like your version needs the `encodeBase64`

tjones
2021-09-22 09:30
You're right that the casing shouldn't matter. I should lower case ours, so it matches the string in the rust source, for better searchability later

yann.courtel
2021-09-22 09:30
Thanks @tjones Have a few things to try

tjones
2021-09-22 09:31
Awesome!

tjones
2021-09-22 09:31
I'll get you a link to this bit in our source in case there's surrounding context that's useful


tjones
2021-09-22 09:34
That part of the code could be more straightforward. It was written as a hack when we only had the spec v2 verifier. Let me know if you have questions that you can't answer easily - 5 mins of my time could save you much more of yours.

yann.courtel
2021-09-22 09:34
That does help. Thanks a lot

yann.courtel
2021-09-22 10:00
wow! it now works! Strangest thing in a while When I put 'pact-message-metadata' exactly like the one in the ffi it doesn't work. When I paste your code @tjones , as in PACT_MESSAGE_METADATA it does work!

yann.courtel
2021-09-22 10:01
thanks a lot @tjones for your snippet. I could have spent another day trying to figure that one out!

tjones
2021-09-22 10:27
Welcome! If you're using the FFI v0.0.0 (or possibly v0.0.1) then it's the capitalised one with underscores

matt.fellows
2021-09-22 11:23
Sorry, was doing the whole kids dinner/shower/bed/cleanup/passout routine


matt.fellows
2021-09-22 11:23
not exactly convenient, but it is documented there

matt.fellows
2021-09-22 11:23
We really need a development implementation guide

matt.fellows
2021-09-22 11:24
It?s a lesson learned for this, and we?ll aim not to make that mistake with the plugin work going on

yann.courtel
2021-09-22 11:58
oh yeah @matt.fellows it would have been so much easier if I had read the doc.... true. Well, as long as it's in the lib now, it should not bother us.

matt.fellows
2021-09-22 12:01
my point was that the docs aren?t very accessible (why would you think to look at the CLI docs for the FFI bits) and also that a guide for developers like you/Adam/Mike etc. would be VERY helpful!

matt.fellows
2021-09-22 12:01
(i.e. it?s our fault!)

yann.courtel
2021-09-22 12:02
well, when the next version is out, a doc brainstorming with all these little issues might help :slightly_smiling_face: but no worries. At least it works now. Thanks for the help both.

yann.courtel
2021-09-27 13:35
Hi everyone, This is the PR for the provider messaging: https://github.com/pact-foundation/pact-net/pull/326 I'm having trouble with the latest base -> feature/4.0.0. (some projects have been deleted) Working on it. It takes in account all the comments in this previous draft PR => https://github.com/pact-foundation/pact-net/pull/309

tjones
2021-09-27 14:21
I'm excited to see this happening!

yann.courtel
2021-09-27 14:31
The middleware part was hard to make it easy to use but I think it could be a good base to eventually have a provider state middleware as well.

yann.courtel
2021-09-27 14:44
rebase is all good but still have unit tests issues on some I haven't touched... pending.

yann.courtel
2021-09-27 14:51
~ok,~

yann.courtel
2021-09-27 14:51
al

yann.courtel
2021-09-27 14:51
l set

yann.courtel
2021-09-27 14:52
all set :slightly_smiling_face:

yann.courtel
2021-10-05 09:59
All comments have been taken in consideration / answered. I need to create another PR for the Unit tests of the future middlewares in the AspNetCore project

pact544
2021-10-06 20:00
@yann.courtel @matt.fellows I ended up writing some quite detailed comments on the messaging provider MR, so instead of making you do all of that I created a branch off Yann's branch with my suggestions implemented: https://github.com/pact-foundation/pact-net/tree/feature/messaging-provider-suggestions That commit can just be merged into Yann's branch. I think it provides an overall cleaner API, is safer due to the type state pattern, and removes the need for `PactNet.AspNetCore` to reference `PactNet.Native` which is probably a big deal for people consuming those NuGets. I've also made a general suggestion about providing an entire turnkey solution for the messaging verifier REST API instead of just the middleware. I think that would make it much easier for users if they don't have to create the API project themselves then add our small middleware, if instead they just let us spin up the REST API for them without needing to worry about it. They don't even need to know it's there. Anyway, let me know what you think!

matt.fellows
2021-10-06 23:34
This is what I?ve been saying for ages! The users shouldn?t need to know that to verify a message that the implementation requires an HTTP endpoint to communicate with. That should be hidden away completely as an implementation detail in the framework (and appropriate debug logging available if/when shit hits the fan) Perhaps I wasn?t explaining myself previously very well, or now that you understand the implemenation it means something more to you. For reference, this is the architecture that other languages have basically adopted to do this: https://github.com/pact-foundation/pact-message-demo

matt.fellows
2021-10-06 23:35
The best part of it is, ideally, you could re-use this for the provider state handling also (i.e. point the provider state handlers for HTTP pact at a similar framework initiatide HTTP endpoint). Provider states can than be mapped in a similar way.



matt.fellows
2021-10-06 23:35
all of that is enabled by the framework provided API

matt.fellows
2021-10-06 23:36
Users essentially just pass anonymous functions and the framework attaches them to middleware and executes for them

yann.courtel
2021-10-07 07:21
I love the suggestions and am incorporating them right now. For the server solution instead of starting the REST API, it makes a lot of sense it terms of framework and language compatibility. But for the moment, I would focus on the middleware and we can easily make it evolve to the server solution, most likely in another project all together. Thanks for the comments

yann.courtel
2021-10-07 07:24
@matt.fellows that was the plan yes. The package having the messaging middleware could have all the middlewares used in the samples apps. (provider states, auth, etc)

yann.courtel
2021-10-07 07:27
The big problem for now is that from my understanding, the RUST needs an HTTP endpoint. Basically, like @pact544 was saying, each lib for each language will need to add an endpoint on the fly and configure it well for messaging purposes. The good thing with that approach is that we could use that server solution for any protocol we want to support in the future.

matt.fellows
2021-10-07 07:39
Yep that's right. The diagram above was back for the ruby implementation but the principle is the same

matt.fellows
2021-10-07 07:40
It could be done over FFI but bidirectional FFI calls are even more :exploding_head:. HTTP at least is a standard and is ubiquitous

yann.courtel
2021-10-07 07:40
I think at the time, we were so tightly coupled with HTTP, we just thought that'd be the only way we could make the messaging work :slightly_smiling_face:

matt.fellows
2021-10-07 07:40
Also wait until plugins come in. Would you and @pact544 like a briefing on that progress?

matt.fellows
2021-10-07 07:41
I have to run to dinner but let us know if/when the time is right

yann.courtel
2021-10-07 07:42
That'd be nice, we will need to make timezone work ^^ I was working at 10pm yesterday to answer adam's comments and I think now it's you who's working overtime. Let's plan that next week maybe

yann.courtel
2021-10-07 07:42
given our availability

matt.fellows
2021-10-07 07:45
I always work late nights to accommodate EU/US so we'll fit in with you guys.

yann.courtel
2021-10-07 07:45
I know :raised_hands: Thanks a lot

pact544
2021-10-07 07:49
Is it possible to just merge my commit in instead...? That way I still get the credit :joy:

yann.courtel
2021-10-07 07:50
I did cherry-picked it :slightly_smiling_face:

pact544
2021-10-07 07:50
Nice :thumbsup:

yann.courtel
2021-10-07 07:50
funny thing is my computer is acting out and the auth is not working on the push...

yann.courtel
2021-10-07 07:52
hm, changing my windows password triggered the credentials manager to change my git token with my new password.... very annoying

yann.courtel
2021-10-07 07:52
it's pushed :slightly_smiling_face:

yann.courtel
2021-10-07 07:52
I'll finish up some issues I saw whilst adding additional unit tests and we should be good to go

yann.courtel
2021-10-07 07:57
you were thorough, I saw you even added the extensions for adding the options in the DI :slightly_smiling_face:

pact544
2021-10-07 07:57
I am an annoying perfectionist :joy: I'm just reviewing now but I imagine it'll be fine

yann.courtel
2021-10-07 07:58
Yeah I noticed that. I have a lot in my team so I am accustomed to it now ^^

yann.courtel
2021-10-07 07:58
annoying the dynamic doesn't work with fluent assertions....

yann.courtel
2021-10-07 07:59
I saw an extensions that mapped it to an object behind the scene. If we have spare time, that'd be nice to put it lol

yann.courtel
2021-10-07 08:02
That's amazing you can literally use the same approach with the provider states now

yann.courtel
2021-10-07 09:06
All good @pact544 for approve and merge

pact544
2021-10-07 09:06
Nice, I'll check it now

yann.courtel
2021-10-07 09:07
I didn't add anything else lol :slightly_smiling_face: the other unit tests will be middleware specific and be part of another PR. Thanks a lot for the suggestion and the work on the verifier

pact544
2021-10-07 09:07
Merged!!! Congrats

yann.courtel
2021-10-07 09:07
:tada::tada: Damn, feels good

yann.courtel
2021-10-08 08:57
Hey everyone, I've started looking into moving the provider state middleware into the new AspNetCore project in the feature/4.0.0 branch. It also gives a V3 PACT compatiblity since the provider in the sample apps didn't test the provider states with parameters for instance. Besides, we've added it on the consumer side so it should be part of the beta version. I'll update the sample app and post some progress here. Thanks a lot.

yann.courtel
2021-10-08 09:00
@tjones and @matt.fellows I saw this https://github.com/pact-foundation/pact-js/#modify-requests-prior-to-verification-request-filters And I was wondering how you handle the execution of provider state handle with parameters. Like highlighted in the V3 Specs : https://github.com/pact-foundation/pact-specification/tree/version-3 Thank you for your feedback.

tjones
2021-10-08 09:11
I?m away from the computer at the moment, but the ffi verifier sends parameters in a json object to the state change endpoint. Pact-js runs a proxy for the provider that catches these state changes (and proxies everything else)

tjones
2021-10-08 09:11
Tomorrow morning I can send you links to the relevant bits of the code

tjones
2021-10-08 09:12
The modification of requests is done with middleware in that proxy too

yann.courtel
2021-10-08 09:13
Ok. Thanks. Yeah it sounds like the V2 will be very easy. In .NET, to dynamically invoke a method, it has to be (of my knowledge) with an infinite array of object (params object[]). The invocation of the method should be made generic and the responsibility is only on the testing project to make sure the method invoked have the same arguments as the provider state in the PACT. Thank you for the infos.



matt.fellows
2021-10-08 09:40
(that?s probably a little messy looking, because we make it backwards compatible with the V2 API, but support params, and also setup/teardown hooks. It can also *return* parameters to support provider state injected values

yann.courtel
2021-10-08 09:44
:open_mouth: you can actually tell if it's a setup or teardown?? nice

yann.courtel
2021-10-08 09:44
That's something the middleware can do indeed

yann.courtel
2021-10-08 09:45
because I assumed everything was only setup methods

matt.fellows
2021-10-08 09:51
yeah, the new verifier will hit the state endpoint on the way up and down, passing a JSON blob each time.


matt.fellows
2021-10-08 09:52
```{ "action: setup|teardown, "params": key/value map (may be a complex data structure), "state": "string description of state from interaction" }```

matt.fellows
2021-10-08 09:54
the state may return a blob of JSON data, where the keys match an expression given in the consumer test. See this example: https://github.com/pact-foundation/pact-js/tree/feat/v3.0.0/examples/v3/provider-state-injected

yann.courtel
2021-10-08 09:55
I'll have a second look after I made the V2, and V3 provider state middleware work :smile: baby steps

yann.courtel
2021-10-08 09:56
Thanks for all the info

matt.fellows
2021-10-08 09:57
For clarity, in terms of the public facing API: ? Both V2 and V3 will be called on setup/teardown ? Only V3 supports state parameters ? Only V3 supports returning provider parameters

pact544
2021-10-14 18:48
#pact-net-development Looking for thoughts on the following idea: For v4 I think we should rename the `PactNet` project in the solution to `PactNet.Abstractions` (since that's what it actually contains now), and rename `PactNet.Native` to `PactNet` instead. The reasoning is that at the moment the installation instructions are slightly unclear - the main `PactNet` package isn't actually what you want to install even though it has the logical main package name. It doesn't actually contain anything useful at all, just interfaces and simple model objects. Instead you actually want to `dotnet add package PactNet.Native` if you want to get anything done. I think that's confusing for users. Microsoft and others follow exactly the example I've outlined above - they have `.Abtractions` versions of all their NuGets which just contain things like the generic interfaces and simple POCOs (like model objects), then the main version without the `.Abstractions` is the one you actually want to use. For example: ? https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection.Abstractions and https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection ? https://www.nuget.org/packages/Microsoft.Extensions.Logging.Abstractions and https://www.nuget.org/packages/Microsoft.Extensions.Logging ? ...and so on for Configuration, Options, FileProviders, Hosting, etc etc etc ? https://www.nuget.org/packages/xunit.abstractions/ and https://www.nuget.org/packages/xunit/ It also makes creating extensions and wrapper packages much easier, because third party library authors only need to depend on the `Abstractions` public members, since the internals of the main package are all private. For example, this package ships logging integration for xUnit and only needs to depend on `xunit.abstractions`: https://www.nuget.org/packages/Divergic.Logging.Xunit/

yann.courtel
2021-10-15 09:25
Hi @pact544 I think it's a good idea since indeed, why should you need the native package to have the implementation at all. It's more straightforward that way. We will need to do some cleanup of some classes we've put in the PactNet (would-be .Abstractions) project to move it to the implementations project.

yann.courtel
2021-10-15 09:36
Hey guys, I seem to have the code working but have trouble reconciling the current sample API example to work properly. Mainly because of the pact specification tied to the sample APIs. I was thinking of splitting the main folder to have different APIs all together for the different PACT specs version. Does that make sense?

yann.courtel
2021-10-15 09:37
or even EventAPI_PACT_V2 and EventAPI_PACT_V3 to be ultra clear :slightly_smiling_face:

yann.courtel
2021-10-15 09:40
or another way, a different folder structure like : samples / PACT_V2 / EventApi samples / PACT_V3 / EventApi / EventImporter samples / PACT_V4 / ........ ......

pact544
2021-10-15 17:11
Yeah I'm gonna try it out locally and see what it ends up looking like. We'll need to be mindful of keeping anything in Abstractions which may be needed by a plug-in, extension or alternative implementation. Off the top of my head it may be that nothing needs to move at all. Like if we ever do reimplement PactNet.Remote as an alternative backend, that should only have to rely on Abstractions and should never need to rely on PactNet (with the native default implementation inside). I'll also keep the root namespace of Abstractions just as PactNet just so that we don't end up with users having to import loads of namespaces. That's what Microsoft do with their packages also.

pact544
2021-10-15 18:59
OK I've done that. Considering the scope of the change the diff actually isn't too bad! I see what you mean about perhaps needing to move things out, but at the same time I don't think they're anywhere to go now. Perhaps we should rename `Abstractions` to `Core` instead? The only misfit is the new message scenarios stuff. You'd still want that if you did an alternate implementation so it belongs in the 'central' package, but it's not an 'abstraction'.

tjones
2021-10-16 00:20
It's good to have some consistency of API across the different frameworks - the original guideline was "close to the ruby implementation", but I don't think the ruby implementation supports the pact spec v3, so perhaps that guideline falls down

matt.fellows
2021-10-17 10:17
Pact JS has the format: `examples/vX/example1`

matt.fellows
2021-10-17 10:17
But probably it matters less if the docs can deep link to it

tjones
2021-10-17 23:12
Oh, sorry. I misunderstood the question. Matt has it right

yann.courtel
2021-10-18 07:13
In my last PR (the WIP provider state middleware), I actually made the middleware rely on an "accessor" interface / class which is an abstraction so the Scenarios class will be internal to the now PactNet package

yann.courtel
2021-10-18 08:40
I tested locally and on the provider side I don't need the Native package any longer!

yann.courtel
2021-10-18 08:43
The only thing remaining are the extensions methods that forces the consumer test project to use the Native one in order to chose a certain implementation of the backend (remote or native) but that's how it's supposed to work anyway going forward, right?

yann.courtel
2021-10-18 08:46
hm, I see the tricky part here. We don't want to UsingNativeBackend or UsingRemoteBackend to end up in the interface. Would that be such a horrible thing to do, design wise?

yann.courtel
2021-10-18 08:48
For instance, the IPactV2 would have the old http ruby service and the IPactV3 the native backend. If we have another backend service in V4 (why not) we would add it to the new IPactV4 interface.

yann.courtel
2021-10-18 12:46
I see that you put the rootnamespace as pactnet so it no longer matters in the sample apps :slightly_smiling_face:

yann.courtel
2021-10-18 12:55
I heard you @matt.fellows but I will leave PactV2 or PactV3 to avoid any confusion with the pactnet major lib version number vs the pact specs number :slightly_smiling_face:


edanielsen
2021-11-01 04:17
Hi @pact544, I see that since October 6 (this commit: `5171d8c5cf8b042fdda1af6cd01184e15ff7dab1`), the `WithPublishedResults` method has been removed from the pact verifier. Was that on purpose or an accident? Is there now a different way to publish verified results back to the pact broker?

yann.courtel
2021-11-04 10:14
Hi @edanielsen it looks like it will be included in the pact broker options in the future. See here: https://github.com/pact-foundation/pact-net/pull/339#issuecomment-954611791

edanielsen
2021-11-05 10:01
Ok, thank you @yann.courtel

mch
2021-12-29 13:48
has joined #pact-net-development

mch
2022-01-02 20:29
Hi, could you tell me when this issue is expected to be solved: https://github.com/pact-foundation/pact-net/issues/327? Can I contribute to it or is it currently worked on?

matt.fellows
2022-01-03 03:11
Looks like a pretty trivial fix, if you?re up for a PR that?d be great!

mch
2022-01-03 06:36
What should be the starting branch for this, master or feature/4.0.0?

matt.fellows
2022-01-03 07:10
This specific request master (the standalone is only used by master) but the feature needs to be in 4.x.x as well (I don't know if it's been implemented in it already tho)

mch
2022-01-03 10:35
@matt.fellows It doesn't seem to be currently implemented in feature/4.0.0

matt.fellows
2022-01-03 10:37
Thanks. The branch property exists on the latest rust core, so if you were up for doing it in the 4.x.x branch also that would be :pray:

matt.fellows
2022-01-03 10:37
I haven?t heard from the .NET maintainers for a little while, so I suspect they are on leave over this time of year

mch
2022-01-03 19:46
Pull request ready :slightly_smiling_face:

tomas.sakinis
2022-03-04 06:37
has joined #pact-net-development

henit.laxmicant
2022-04-08 14:21
has joined #pact-net-development

yousafn
2022-04-29 14:38
has joined #pact-net-development

rholshausen
2022-05-05 00:32
has joined #pact-net-development

heytaco
2022-05-09 18:00
has joined #pact-net-development

orbit
2022-05-09 18:01
has joined #pact-net-development

tjones
2022-05-16 08:48
@tjones has left the channel

tomas.sakinis
2022-05-20 08:41
@tomas.sakinis has left the channel

slacksync
2022-06-08 17:22
has joined #pact-net-development

duynguyenptithcm
2022-08-20 07:25
has joined #pact-net-development

orbit
2022-12-01 15:45
has joined #pact-net-development

pallavi.bose
2023-02-08 13:30
has joined #pact-net-development

courtel.yann
2023-02-28 08:07
has joined #pact-net-development

pact544
2023-05-05 10:46
#pact-net-development Please see the below RFC for proposed breaking changes to PactVerifier for Pactnet 5.0 https://github.com/pact-foundation/pact-net/issues/457

bas
2023-06-15 14:52
has joined #pact-net-development

joshua.ellis
2023-09-20 06:40
has joined #pact-net-development

jo.laing
2024-02-06 14:04
has joined #pact-net-development