• 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

76.59
/message/v4/synchronous_message.go
1
package v4
2

3
import (
4
        "fmt"
5
        "log"
6
        "os"
7
        "path/filepath"
8
        "strings"
9
        "testing"
10

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

18
type SynchronousPact struct {
19
        config Config
20

21
        // Reference to the native rust handle
22
        mockserver *native.MessageServer
23
}
24

25
// SynchronousMessage contains a req/res message
26
// It is currently an empty struct to allow future expansion
27
type SynchronousMessage struct {
28
        // TODO: should we pass this in? Probably need to be able to reify the message
29
        //       in these cases
30
        Request MessageContents
31

32
        // Currently only support a single response, but support may be added for multiple
33
        // responses to be given in the future
34
        Response []MessageContents
35
}
36

37
// SynchronousMessageBuilder is a representation of a single, bidirectional message
38
type SynchronousMessageBuilder struct {
39
}
40

41
// Given specifies a provider state
42
func (m *UnconfiguredSynchronousMessageBuilder) Given(state string) *UnconfiguredSynchronousMessageBuilder {
24✔
43
        m.messageHandle.Given(state)
24✔
44

24✔
45
        return &UnconfiguredSynchronousMessageBuilder{
24✔
46
                pact:          m.pact,
24✔
47
                messageHandle: m.messageHandle,
24✔
48
        }
24✔
49
}
24✔
50

51
// Given specifies a provider state
52
func (m *UnconfiguredSynchronousMessageBuilder) GivenWithParameter(state models.ProviderState) *UnconfiguredSynchronousMessageBuilder {
×
53
        m.messageHandle.GivenWithParameter(state.Name, state.Parameters)
×
54

×
55
        return &UnconfiguredSynchronousMessageBuilder{
×
56
                pact:          m.pact,
×
57
                messageHandle: m.messageHandle,
×
UNCOV
58
        }
×
UNCOV
59
}
×
60

61
type UnconfiguredSynchronousMessageBuilder struct {
62
        messageHandle *native.Message
63
        pact          *SynchronousPact
64
}
65

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

74
        return &SynchronousMessageWithPlugin{
18✔
75
                pact:          m.pact,
18✔
76
                messageHandle: m.messageHandle,
18✔
77
        }
18✔
78
}
79

80
// UsingPlugin enables a plugin for use in the current test case
81
func (m *SynchronousMessageWithPlugin) UsingPlugin(config PluginConfig) *SynchronousMessageWithPlugin {
×
82
        err := m.pact.mockserver.UsingPlugin(config.Plugin, config.Version)
×
83
        if err != nil {
×
UNCOV
84
                log.Println("[ERROR] failed to add plugin:", err)
×
UNCOV
85
                panic(err)
×
86
        }
87

UNCOV
88
        return m
×
89
}
90

91
// AddMessage creates a new asynchronous consumer expectation
92
func (m *UnconfiguredSynchronousMessageBuilder) WithRequest(r RequestBuilderFunc) *SynchronousMessageWithRequest {
6✔
93
        r(&SynchronousMessageWithRequestBuilder{
6✔
94
                messageHandle: m.messageHandle,
6✔
95
                pact:          m.pact,
6✔
96
        })
6✔
97

6✔
98
        return &SynchronousMessageWithRequest{
6✔
99
                pact:          m.pact,
6✔
100
                messageHandle: m.messageHandle,
6✔
101
        }
6✔
102
}
6✔
103

104
type SynchronousMessageWithRequest struct {
105
        messageHandle *native.Message
106
        pact          *SynchronousPact
107
}
108

109
type RequestBuilderFunc func(*SynchronousMessageWithRequestBuilder)
110

111
type SynchronousMessageWithRequestBuilder struct {
112
        messageHandle *native.Message
113
        pact          *SynchronousPact
114
}
115

116
// WithMetadata specifies message-implementation specific metadata
117
// to go with the content
118
// func (m *Message) WithMetadata(metadata MapMatcher) *Message {
119
func (m *SynchronousMessageWithRequestBuilder) WithMetadata(metadata map[string]string) *SynchronousMessageWithRequestBuilder {
6✔
120
        m.messageHandle.WithRequestMetadata(metadata)
6✔
121

6✔
122
        return m
6✔
123
}
6✔
124

125
// WithContent specifies the payload in bytes that the consumer expects to receive
126
func (m *SynchronousMessageWithRequestBuilder) WithContent(contentType string, body []byte) *SynchronousMessageWithRequestBuilder {
×
127
        m.messageHandle.WithContents(native.INTERACTION_PART_REQUEST, contentType, body)
×
128

×
UNCOV
129
        return m
×
UNCOV
130
}
×
131

132
// WithJSONContent specifies the payload as an object (to be marshalled to WithJSONContent) that
133
// is expected to be consumed
134
func (m *SynchronousMessageWithRequestBuilder) WithJSONContent(content interface{}) *SynchronousMessageWithRequestBuilder {
6✔
135
        m.messageHandle.WithRequestJSONContents(content)
6✔
136

6✔
137
        return m
6✔
138
}
6✔
139

140
// AddMessage creates a new asynchronous consumer expectation
141
func (m *SynchronousMessageWithRequest) WithResponse(builder ResponseBuilderFunc) *SynchronousMessageWithResponse {
6✔
142
        builder(&SynchronousMessageWithResponseBuilder{
6✔
143
                messageHandle: m.messageHandle,
6✔
144
                pact:          m.pact,
6✔
145
        })
6✔
146

6✔
147
        return &SynchronousMessageWithResponse{
6✔
148
                pact:          m.pact,
6✔
149
                messageHandle: m.messageHandle,
6✔
150
        }
6✔
151
}
6✔
152

153
type SynchronousMessageWithResponse struct {
154
        messageHandle *native.Message
155
        pact          *SynchronousPact
156
}
157

158
type ResponseBuilderFunc func(*SynchronousMessageWithResponseBuilder)
159

160
type SynchronousMessageWithResponseBuilder struct {
161
        messageHandle *native.Message
162
        pact          *SynchronousPact
163
}
164

165
// WithMetadata specifies message-implementation specific metadata
166
// to go with the content
167
// func (m *Message) WithMetadata(metadata MapMatcher) *Message {
168
func (m *SynchronousMessageWithResponseBuilder) WithMetadata(metadata map[string]string) *SynchronousMessageWithResponseBuilder {
6✔
169
        m.messageHandle.WithResponseMetadata(metadata)
6✔
170

6✔
171
        return m
6✔
172
}
6✔
173

174
// WithContent specifies the payload in bytes that the consumer expects to receive
175
// May be called multiple times, with each call appeding a new response to the interaction
176
func (m *SynchronousMessageWithResponseBuilder) WithContent(contentType string, body []byte) *SynchronousMessageWithResponseBuilder {
×
177
        m.messageHandle.WithContents(native.INTERACTION_PART_RESPONSE, contentType, body)
×
178

×
UNCOV
179
        return m
×
UNCOV
180
}
×
181

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

6✔
187
        return m
6✔
188
}
6✔
189

190
type SynchronousMessageWithPlugin struct {
191
        messageHandle *native.Message
192
        pact          *SynchronousPact
193
}
194

195
func (s *SynchronousMessageWithPlugin) WithContents(contents string, contentType string) *SynchronousMessageWithPluginContents {
18✔
196
        _ = s.messageHandle.WithPluginInteractionContents(native.INTERACTION_PART_REQUEST, contentType, contents)
18✔
197

18✔
198
        return &SynchronousMessageWithPluginContents{
18✔
199
                pact:          s.pact,
18✔
200
                messageHandle: s.messageHandle,
18✔
201
        }
18✔
202
}
18✔
203

204
type SynchronousMessageWithPluginContents struct {
205
        messageHandle *native.Message
206
        pact          *SynchronousPact
207
}
208

209
// ExecuteTest runs the current test case against a Mock Service.
210
// Will cleanup interactions between tests within a suite
211
// and write the pact file if successful
212
func (m *SynchronousMessageWithPluginContents) ExecuteTest(t *testing.T, integrationTest func(m SynchronousMessage) error) error {
6✔
213
        defer m.pact.mockserver.CleanupPlugins()
6✔
214
        message, err := getSynchronousMessageWithContents(m.messageHandle)
6✔
215
        if err != nil {
6✔
UNCOV
216
                return err
×
UNCOV
217
        }
×
218

219
        err = integrationTest(message)
6✔
220

6✔
221
        if err != nil {
6✔
UNCOV
222
                return err
×
UNCOV
223
        }
×
224

225
        return m.pact.mockserver.WritePactFile(m.pact.config.PactDir, false)
6✔
226
}
227

228
func (s *SynchronousMessageWithPluginContents) StartTransport(transport string, address string, config map[string][]interface{}) *SynchronousMessageWithTransport {
12✔
229
        port, err := s.pact.mockserver.StartTransport(transport, address, 0, make(map[string][]interface{}))
12✔
230

12✔
231
        if err != nil {
12✔
UNCOV
232
                log.Fatalln("unable to start plugin transport:", err)
×
UNCOV
233
        }
×
234

235
        return &SynchronousMessageWithTransport{
12✔
236
                pact:          s.pact,
12✔
237
                messageHandle: s.messageHandle,
12✔
238
                transport: TransportConfig{
12✔
239
                        Port:    port,
12✔
240
                        Address: address,
12✔
241
                },
12✔
242
        }
12✔
243
}
244

245
type SynchronousMessageWithTransport struct {
246
        messageHandle *native.Message
247
        pact          *SynchronousPact
248
        transport     TransportConfig
249
}
250

251
func (s *SynchronousMessageWithTransport) ExecuteTest(t *testing.T, integrationTest func(tc TransportConfig, m SynchronousMessage) error) error {
12✔
252
        defer s.pact.mockserver.CleanupMockServer(s.transport.Port)
12✔
253
        defer s.pact.mockserver.CleanupPlugins()
12✔
254
        message, err := getSynchronousMessageWithContents(s.messageHandle)
12✔
255
        if err != nil {
12✔
UNCOV
256
                return err
×
UNCOV
257
        }
×
258

259
        err = integrationTest(s.transport, message)
12✔
260

12✔
261
        // matched := s.pact.mockserver.MockServerMatched(s.transport.Port)
12✔
262
        // log.Println("MATHED??????????", matched)
12✔
263
        mismatches := s.pact.mockserver.MockServerMismatchedRequests(s.transport.Port)
12✔
264

12✔
265
        if len(mismatches) > 0 {
24✔
266
                return fmt.Errorf("pact validation failed: %+v", mismatches)
12✔
267
        }
12✔
268

269
        if err != nil {
×
UNCOV
270
                return err
×
271
        }
×
272

UNCOV
273
        return s.pact.mockserver.WritePactFileForServer(s.transport.Port, s.pact.config.PactDir, false)
×
274
}
275

276
type PluginConfig struct {
277
        Plugin  string
278
        Version string
279
}
280

281
func NewSynchronousPact(config Config) (*SynchronousPact, error) {
24✔
282
        provider := &SynchronousPact{
24✔
283
                config: config,
24✔
284
        }
24✔
285
        err := provider.validateConfig()
24✔
286

24✔
287
        if err != nil {
24✔
UNCOV
288
                return nil, err
×
UNCOV
289
        }
×
290

291
        native.Init(string(logging.LogLevel()))
24✔
292

24✔
293
        return provider, err
24✔
294
}
295

296
// validateConfig validates the configuration for the consumer test
297
func (m *SynchronousPact) validateConfig() error {
24✔
298
        log.Println("[DEBUG] pact synchronous message validate config")
24✔
299
        dir, _ := os.Getwd()
24✔
300

24✔
301
        if m.config.PactDir == "" {
30✔
302
                m.config.PactDir = filepath.Join(dir, "pacts")
6✔
303
        }
6✔
304

305
        m.mockserver = native.NewMessageServer(m.config.Consumer, m.config.Provider)
24✔
306
        m.mockserver.WithSpecificationVersion(mockserver.SPECIFICATION_VERSION_V4)
24✔
307
        m.mockserver.WithMetadata("pact-go", "version", strings.TrimPrefix(command.Version, "v"))
24✔
308

24✔
309
        return nil
24✔
310
}
311

312
func (m *SynchronousPact) AddSynchronousMessage(description string) *UnconfiguredSynchronousMessageBuilder {
24✔
313
        log.Println("[DEBUG] add sync message")
24✔
314

24✔
315
        message := m.mockserver.NewSyncMessageInteraction(description)
24✔
316

24✔
317
        return &UnconfiguredSynchronousMessageBuilder{
24✔
318
                messageHandle: message,
24✔
319
                pact:          m,
24✔
320
        }
24✔
321
}
24✔
322

323
// ExecuteTest runs the current test case against a Mock Service.
324
// Will cleanup interactions between tests within a suite
325
// and write the pact file if successful
326
func (m *SynchronousMessageWithResponse) ExecuteTest(t *testing.T, integrationTest func(md SynchronousMessage) error) error {
6✔
327
        message, err := getSynchronousMessageWithContents(m.messageHandle)
6✔
328
        if err != nil {
6✔
UNCOV
329
                return err
×
UNCOV
330
        }
×
331

332
        err = integrationTest(message)
6✔
333

6✔
334
        if err != nil {
6✔
UNCOV
335
                return err
×
UNCOV
336
        }
×
337

338
        return m.pact.mockserver.WritePactFile(m.pact.config.PactDir, false)
6✔
339
}
340

341
func getSynchronousMessageWithContents(message *native.Message) (SynchronousMessage, error) {
24✔
342
        var m SynchronousMessage
24✔
343

24✔
344
        contents, err := message.GetMessageRequestContents()
24✔
345
        if err != nil {
24✔
UNCOV
346
                return m, err
×
UNCOV
347
        }
×
348

349
        responses, err := message.GetMessageResponseContents()
24✔
350
        if err != nil {
24✔
UNCOV
351
                return m, err
×
UNCOV
352
        }
×
353

354
        response := make([]MessageContents, len(responses))
24✔
355
        for i, r := range responses {
48✔
356
                response[i] = MessageContents{
24✔
357
                        Contents: r,
24✔
358
                }
24✔
359
        }
24✔
360

361
        return SynchronousMessage{
24✔
362
                Request: MessageContents{
24✔
363
                        Contents: contents,
24✔
364
                },
24✔
365
                Response: response,
24✔
366
        }, nil
24✔
367
}
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