• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pact-foundation / pact-go / 13706004865

06 Mar 2025 06:51PM UTC coverage: 28.238% (+0.03%) from 28.209%
13706004865

push

github

YOU54F
fix: strip v prefix from pact-go verifier version

0 of 1 new or added line in 1 file covered. (0.0%)

140 existing lines in 4 files now uncovered.

1805 of 6392 relevant lines covered (28.24%)

8.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.94
/message/v4/asynchronous_message.go
1
package v4
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "log"
7
        "os"
8
        "path/filepath"
9
        "reflect"
10
        "strings"
11
        "testing"
12

13
        "github.com/pact-foundation/pact-go/v2/command"
14
        "github.com/pact-foundation/pact-go/v2/internal/native"
15
        mockserver "github.com/pact-foundation/pact-go/v2/internal/native"
16
        logging "github.com/pact-foundation/pact-go/v2/log"
17
        "github.com/pact-foundation/pact-go/v2/models"
18
)
19

20
// Builder 1: Async with no plugin/transport
21
// Builder 2: Async with plugin content no transport
22
// Builder 3: Async with plugin content + transport
23

24
type AsynchronousMessageBuilder struct {
25
        messageHandle *mockserver.Message
26
        pact          *AsynchronousPact
27

28
        // Type to Marshal content into when sending back to the consumer
29
        // Defaults to interface{}
30
        Type interface{}
31

32
        // The handler for this message
33
        handler AsynchronousConsumer
34
}
35

36
// Given specifies a provider state. Optional.
37
func (m *AsynchronousMessageBuilder) Given(state string) *AsynchronousMessageBuilder {
18✔
38
        m.messageHandle.Given(state)
18✔
39

18✔
40
        return m
18✔
41
}
18✔
42

43
// Given specifies a provider state. Optional.
44
func (m *AsynchronousMessageBuilder) GivenWithParameter(state models.ProviderState) *AsynchronousMessageBuilder {
×
45
        m.messageHandle.GivenWithParameter(state.Name, state.Parameters)
×
46

×
UNCOV
47
        return m
×
UNCOV
48
}
×
49

50
// ExpectsToReceive specifies the content it is expecting to be
51
// given from the Provider. The function must be able to handle this
52
// message for the interaction to succeed.
53
func (m *AsynchronousMessageBuilder) ExpectsToReceive(description string) *UnconfiguredAsynchronousMessageBuilder {
12✔
54
        m.messageHandle.ExpectsToReceive(description)
12✔
55

12✔
56
        return &UnconfiguredAsynchronousMessageBuilder{
12✔
57
                rootBuilder: m,
12✔
58
        }
12✔
59
}
12✔
60

61
type UnconfiguredAsynchronousMessageBuilder struct {
62
        rootBuilder *AsynchronousMessageBuilder
63
}
64

65
// UsingPlugin enables a plugin for use in the current test case
66
func (m *UnconfiguredAsynchronousMessageBuilder) UsingPlugin(config PluginConfig) *AsynchronousMessageWithPlugin {
6✔
67
        err := m.rootBuilder.pact.messageserver.UsingPlugin(config.Plugin, config.Version)
6✔
68
        if err != nil {
6✔
UNCOV
69
                log.Println("[ERROR] failed to add plugin:", err)
×
UNCOV
70
                panic(err)
×
71
        }
72

73
        return &AsynchronousMessageWithPlugin{
6✔
74
                rootBuilder: m.rootBuilder,
6✔
75
        }
6✔
76
}
77

78
type AsynchronousMessageWithPlugin struct {
79
        rootBuilder *AsynchronousMessageBuilder
80
}
81

82
func (s *AsynchronousMessageWithPlugin) WithContents(contents string, contentType string) *AsynchronousMessageWithPluginContents {
6✔
83
        err := s.rootBuilder.messageHandle.WithPluginInteractionContents(native.INTERACTION_PART_REQUEST, contentType, contents)
6✔
84
        if err != nil {
6✔
UNCOV
85
                log.Println("[ERROR] failed to get plugin content from message handle:", err)
×
UNCOV
86
                panic(err)
×
87
        }
88

89
        return &AsynchronousMessageWithPluginContents{
6✔
90
                rootBuilder: s.rootBuilder,
6✔
91
        }
6✔
92
}
93

94
type AsynchronousMessageWithPluginContents struct {
95
        rootBuilder *AsynchronousMessageBuilder
96
}
97

98
func (s *AsynchronousMessageWithPluginContents) ExecuteTest(t *testing.T, integrationTest func(m AsynchronousMessage) error) error {
6✔
99
        defer s.rootBuilder.pact.messageserver.CleanupPlugins()
6✔
100
        message, err := getAsynchronousMessageWithReifiedContents(s.rootBuilder.messageHandle, s.rootBuilder.Type)
6✔
101
        if err != nil {
6✔
UNCOV
102
                return err
×
UNCOV
103
        }
×
104

105
        fmt.Println()
6✔
106
        err = integrationTest(message)
6✔
107

6✔
108
        if err != nil {
6✔
UNCOV
109
                return err
×
UNCOV
110
        }
×
111

112
        return s.rootBuilder.pact.messageserver.WritePactFile(s.rootBuilder.pact.config.PactDir, false)
6✔
113
}
114

115
func (s *AsynchronousMessageWithPluginContents) StartTransport(transport string, address string, config map[string][]interface{}) *AsynchronousMessageWithTransport {
×
116
        port, err := s.rootBuilder.pact.messageserver.StartTransport(transport, address, 0, make(map[string][]interface{}))
×
117

×
118
        if err != nil {
×
UNCOV
119
                log.Fatalln("unable to start plugin transport:", err)
×
120
        }
×
121

122
        return &AsynchronousMessageWithTransport{
×
123
                rootBuilder: s.rootBuilder,
×
124
                transport: TransportConfig{
×
125
                        Port:    port,
×
126
                        Address: address,
×
UNCOV
127
                },
×
UNCOV
128
        }
×
129
}
130

131
type AsynchronousMessageWithTransport struct {
132
        rootBuilder *AsynchronousMessageBuilder
133
        transport   TransportConfig
134
}
135

136
func (s *AsynchronousMessageWithTransport) ExecuteTest(t *testing.T, integrationTest func(tc TransportConfig, m AsynchronousMessage) error) error {
×
137
        defer s.rootBuilder.pact.messageserver.CleanupMockServer(s.transport.Port)
×
138
        defer s.rootBuilder.pact.messageserver.CleanupPlugins()
×
139
        message, err := getAsynchronousMessageWithReifiedContents(s.rootBuilder.messageHandle, s.rootBuilder.Type)
×
140
        if err != nil {
×
UNCOV
141
                return err
×
142
        }
×
143

144
        err = integrationTest(s.transport, message)
×
145

×
146
        if err != nil {
×
UNCOV
147
                return err
×
148
        }
×
149

150
        mismatches := s.rootBuilder.pact.messageserver.MockServerMismatchedRequests(s.transport.Port)
×
151

×
152
        if len(mismatches) > 0 {
×
UNCOV
153
                return fmt.Errorf("pact validation failed: %+v", mismatches)
×
154
        }
×
155

UNCOV
156
        return s.rootBuilder.pact.messageserver.WritePactFileForServer(s.transport.Port, s.rootBuilder.pact.config.PactDir, false)
×
157
}
158

159
// WithMetadata specifies message-implementation specific metadata
160
// to go with the content
161
// func (m *Message) WithMetadata(metadata MapMatcher) *Message {
162
func (m *UnconfiguredAsynchronousMessageBuilder) WithMetadata(metadata map[string]string) *UnconfiguredAsynchronousMessageBuilder {
×
163
        m.rootBuilder.messageHandle.WithMetadata(metadata)
×
164

×
UNCOV
165
        return m
×
UNCOV
166
}
×
167

168
type AsynchronousMessageWithContents struct {
169
        rootBuilder *AsynchronousMessageBuilder
170
}
171

172
// WithContent specifies the payload in bytes that the consumer expects to receive
173
func (m *UnconfiguredAsynchronousMessageBuilder) WithContent(contentType string, body []byte) *AsynchronousMessageWithContents {
×
174
        m.rootBuilder.messageHandle.WithContents(mockserver.INTERACTION_PART_REQUEST, contentType, body)
×
175

×
176
        return &AsynchronousMessageWithContents{
×
177
                rootBuilder: m.rootBuilder,
×
UNCOV
178
        }
×
UNCOV
179
}
×
180

181
// WithJSONContent specifies the payload as an object (to be marshalled to WithJSONContent) that
182
// is expected to be consumed
183
func (m *UnconfiguredAsynchronousMessageBuilder) WithJSONContent(content interface{}) *AsynchronousMessageWithContents {
6✔
184
        m.rootBuilder.messageHandle.WithRequestJSONContents(content)
6✔
185

6✔
186
        return &AsynchronousMessageWithContents{
6✔
187
                rootBuilder: m.rootBuilder,
6✔
188
        }
6✔
189
}
6✔
190

191
// AsType specifies that the content sent through to the
192
// consumer handler should be sent as the given type
193
func (m *AsynchronousMessageWithContents) AsType(t interface{}) *AsynchronousMessageWithContents {
6✔
194
        log.Println("[DEBUG] setting Message decoding to type:", reflect.TypeOf(t))
6✔
195
        m.rootBuilder.Type = t
6✔
196

6✔
197
        return m
6✔
198
}
6✔
199

200
// The function that will consume the message
201
func (m *AsynchronousMessageWithContents) ConsumedBy(handler AsynchronousConsumer) *AsynchronousMessageWithConsumer {
6✔
202
        m.rootBuilder.handler = handler
6✔
203

6✔
204
        return &AsynchronousMessageWithConsumer{
6✔
205
                rootBuilder: m.rootBuilder,
6✔
206
        }
6✔
207
}
6✔
208

209
type AsynchronousMessageWithConsumer struct {
210
        rootBuilder *AsynchronousMessageBuilder
211
}
212

213
// The function that will consume the message
214
func (m *AsynchronousMessageWithConsumer) Verify(t *testing.T) error {
6✔
215
        return m.rootBuilder.pact.Verify(t, m.rootBuilder, m.rootBuilder.handler)
6✔
216
}
6✔
217

218
type AsynchronousPact struct {
219
        config Config
220

221
        // Reference to the native rust handle
222
        messageserver *mockserver.MessageServer
223
}
224

225
func NewAsynchronousPact(config Config) (*AsynchronousPact, error) {
12✔
226
        provider := &AsynchronousPact{
12✔
227
                config: config,
12✔
228
        }
12✔
229
        err := provider.validateConfig()
12✔
230

12✔
231
        if err != nil {
12✔
UNCOV
232
                return nil, err
×
UNCOV
233
        }
×
234

235
        native.Init(string(logging.LogLevel()))
12✔
236

12✔
237
        return provider, err
12✔
238
}
239

240
// validateConfig validates the configuration for the consumer test
241
func (p *AsynchronousPact) validateConfig() error {
12✔
242
        log.Println("[DEBUG] pact message validate config")
12✔
243
        dir, _ := os.Getwd()
12✔
244

12✔
245
        if p.config.PactDir == "" {
12✔
UNCOV
246
                p.config.PactDir = filepath.Join(dir, "pacts")
×
UNCOV
247
        }
×
248

249
        p.messageserver = mockserver.NewMessageServer(p.config.Consumer, p.config.Provider)
12✔
250
        p.messageserver.WithSpecificationVersion(mockserver.SPECIFICATION_VERSION_V4)
12✔
251
        p.messageserver.WithMetadata("pact-go", "version", strings.TrimPrefix(command.Version, "v"))
12✔
252

12✔
253
        return nil
12✔
254
}
255

256
// AddMessage creates a new asynchronous consumer expectation
257
// Deprecated: use AddAsynchronousMessage() instead
UNCOV
258
func (p *AsynchronousPact) AddMessage() *AsynchronousMessageBuilder {
×
UNCOV
259
        return p.AddAsynchronousMessage()
×
UNCOV
260
}
×
261

262
// AddMessage creates a new asynchronous consumer expectation
263
func (p *AsynchronousPact) AddAsynchronousMessage() *AsynchronousMessageBuilder {
12✔
264
        log.Println("[DEBUG] add message")
12✔
265

12✔
266
        message := p.messageserver.NewMessage()
12✔
267

12✔
268
        return &AsynchronousMessageBuilder{
12✔
269
                messageHandle: message,
12✔
270
                pact:          p,
12✔
271
        }
12✔
272
}
12✔
273

274
// VerifyMessageConsumerRaw creates a new Pact _message_ interaction to build a testable
275
// interaction.
276
//
277
// A Message Consumer is analagous to a Provider in the HTTP Interaction model.
278
// It is the receiver of an interaction, and needs to be able to handle whatever
279
// request was provided.
280
func (p *AsynchronousPact) verifyMessageConsumerRaw(messageToVerify *AsynchronousMessageBuilder, handler AsynchronousConsumer) error {
6✔
281
        log.Printf("[DEBUG] verify message")
6✔
282

6✔
283
        m, err := getAsynchronousMessageWithReifiedContents(messageToVerify.messageHandle, messageToVerify.Type)
6✔
284
        if err != nil {
6✔
UNCOV
285
                return err
×
UNCOV
286
        }
×
287

288
        // Yield message, and send through handler function
289
        err = handler(m)
6✔
290

6✔
291
        if err != nil {
6✔
UNCOV
292
                return err
×
UNCOV
293
        }
×
294

295
        return p.messageserver.WritePactFile(p.config.PactDir, false)
6✔
296
}
297

298
// VerifyMessageConsumer is a test convience function for VerifyMessageConsumerRaw,
299
// accepting an instance of `*testing.T`
300
func (p *AsynchronousPact) Verify(t *testing.T, message *AsynchronousMessageBuilder, handler AsynchronousConsumer) error {
6✔
301
        err := p.verifyMessageConsumerRaw(message, handler)
6✔
302

6✔
303
        if err != nil {
6✔
UNCOV
304
                t.Errorf("VerifyMessageConsumer failed: %v", err)
×
UNCOV
305
        }
×
306

307
        return err
6✔
308
}
309

310
func getAsynchronousMessageWithContents(message *native.Message) (AsynchronousMessage, error) {
12✔
311
        var m AsynchronousMessage
12✔
312

12✔
313
        contents, err := message.GetMessageRequestContents()
12✔
314
        if err != nil {
12✔
UNCOV
315
                return m, err
×
UNCOV
316
        }
×
317

318
        return AsynchronousMessage{
12✔
319
                Contents: contents,
12✔
320
        }, nil
12✔
321
}
322

323
func getAsynchronousMessageWithReifiedContents(message *mockserver.Message, reifiedType interface{}) (AsynchronousMessage, error) {
12✔
324
        var m AsynchronousMessage
12✔
325
        var err error
12✔
326

12✔
327
        m, err = getAsynchronousMessageWithContents(message)
12✔
328
        if err != nil {
12✔
UNCOV
329
                return m, fmt.Errorf("unexpected response from message server, this is a bug in the framework: %v", err)
×
UNCOV
330
        }
×
331
        log.Println("[DEBUG] reified body raw", string(m.Contents))
12✔
332

12✔
333
        // // 1. Strip out the matchers
12✔
334
        // // Reify the message back to its "example/generated" form
12✔
335
        // body, err := message.GetMessageRequestContents()
12✔
336
        // if err != nil {
12✔
337
        //         return m, fmt.Errorf("unexpected response from message server, this is a bug in the framework: %v", err)
12✔
338
        // }
12✔
339

12✔
340
        log.Println("[DEBUG] unmarshalled into an AsynchronousMessage", m)
12✔
341

12✔
342
        // 2. Convert to an actual type (to avoid wrapping if needed/requested)
12✔
343
        t := reflect.TypeOf(reifiedType)
12✔
344
        if t != nil && t.Name() != "interface" {
18✔
345
                err = json.Unmarshal(m.Contents, &reifiedType)
6✔
346

6✔
347
                if err != nil {
6✔
UNCOV
348
                        return m, fmt.Errorf("unable to narrow type to %v: %v", t.Name(), err)
×
UNCOV
349
                }
×
350

351
                m.Body = reifiedType
6✔
352
        }
353

354
        return m, err
12✔
355
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc