• 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

0.0
/message/v3/asynchronous_message.go
1
package v3
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
// TODO: make a builder?
21

22
// AsynchronousMessageBuilder is a representation of a single, unidirectional message
23
// e.g. MQ, pub/sub, Websocket, Lambda
24
// AsynchronousMessageBuilder is the main implementation of the Pact AsynchronousMessageBuilder interface.
25
type AsynchronousMessageBuilder struct {
26
        messageHandle *mockserver.Message
27
        messagePactV3 *AsynchronousPact
28

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

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

37
type UnconfiguredAsynchronousMessageBuilder struct {
38
        rootBuilder *AsynchronousMessageBuilder
39
}
40

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

×
UNCOV
45
        return m
×
UNCOV
46
}
×
47

48
// Given specifies a provider state. Optional.
49
func (m *AsynchronousMessageBuilder) Given(state string) *AsynchronousMessageBuilder {
×
50
        m.messageHandle.Given(state)
×
51

×
UNCOV
52
        return m
×
UNCOV
53
}
×
54

55
// ExpectsToReceive specifies the content it is expecting to be
56
// given from the Provider. The function must be able to handle this
57
// message for the interaction to succeed.
58
func (m *AsynchronousMessageBuilder) ExpectsToReceive(description string) *UnconfiguredAsynchronousMessageBuilder {
×
59
        m.messageHandle.ExpectsToReceive(description)
×
60

×
61
        return &UnconfiguredAsynchronousMessageBuilder{
×
62
                rootBuilder: m,
×
UNCOV
63
        }
×
UNCOV
64
}
×
65

66
// WithMetadata specifies message-implementation specific metadata
67
// to go with the content
68
// func (m *Message) WithMetadata(metadata MapMatcher) *Message {
69
func (m *UnconfiguredAsynchronousMessageBuilder) WithMetadata(metadata map[string]string) *UnconfiguredAsynchronousMessageBuilder {
×
70
        m.rootBuilder.messageHandle.WithMetadata(metadata)
×
71

×
UNCOV
72
        return m
×
UNCOV
73
}
×
74

75
type AsynchronousMessageBuilderWithContents struct {
76
        rootBuilder *AsynchronousMessageBuilder
77
}
78

79
// WithBinaryContent accepts a binary payload
80
func (m *UnconfiguredAsynchronousMessageBuilder) WithBinaryContent(contentType string, body []byte) *AsynchronousMessageBuilderWithContents {
×
81
        m.rootBuilder.messageHandle.WithContents(mockserver.INTERACTION_PART_REQUEST, contentType, body)
×
82

×
83
        return &AsynchronousMessageBuilderWithContents{
×
84
                rootBuilder: m.rootBuilder,
×
UNCOV
85
        }
×
UNCOV
86
}
×
87

88
// WithContent specifies the payload in bytes that the consumer expects to receive
89
func (m *UnconfiguredAsynchronousMessageBuilder) WithContent(contentType string, body []byte) *AsynchronousMessageBuilderWithContents {
×
90
        m.rootBuilder.messageHandle.WithContents(mockserver.INTERACTION_PART_REQUEST, contentType, body)
×
91

×
92
        return &AsynchronousMessageBuilderWithContents{
×
93
                rootBuilder: m.rootBuilder,
×
UNCOV
94
        }
×
UNCOV
95
}
×
96

97
// WithJSONContent specifies the payload as an object (to be marshalled to WithJSONContent) that
98
// is expected to be consumed
99
func (m *UnconfiguredAsynchronousMessageBuilder) WithJSONContent(content interface{}) *AsynchronousMessageBuilderWithContents {
×
100
        m.rootBuilder.messageHandle.WithRequestJSONContents(content)
×
101

×
102
        return &AsynchronousMessageBuilderWithContents{
×
103
                rootBuilder: m.rootBuilder,
×
UNCOV
104
        }
×
UNCOV
105
}
×
106

107
// // AsType specifies that the content sent through to the
108
// consumer handler should be sent as the given type
109
func (m *AsynchronousMessageBuilderWithContents) AsType(t interface{}) *AsynchronousMessageBuilderWithContents {
×
110
        log.Println("[DEBUG] setting Message decoding to type:", reflect.TypeOf(t))
×
111
        m.rootBuilder.Type = t
×
112

×
UNCOV
113
        return m
×
UNCOV
114
}
×
115

116
type AsynchronousMessageBuilderWithConsumer struct {
117
        rootBuilder *AsynchronousMessageBuilder
118
}
119

120
// The function that will consume the message
121
func (m *AsynchronousMessageBuilderWithContents) ConsumedBy(handler AsynchronousConsumer) *AsynchronousMessageBuilderWithConsumer {
×
122
        m.rootBuilder.handler = handler
×
123

×
124
        return &AsynchronousMessageBuilderWithConsumer{
×
125
                rootBuilder: m.rootBuilder,
×
UNCOV
126
        }
×
UNCOV
127
}
×
128

129
// The function that will consume the message
130
func (m *AsynchronousMessageBuilderWithConsumer) Verify(t *testing.T) error {
×
UNCOV
131
        return m.rootBuilder.messagePactV3.Verify(t, m.rootBuilder, m.rootBuilder.handler)
×
UNCOV
132
}
×
133

134
type AsynchronousPact struct {
135
        config Config
136

137
        // Reference to the native rust handle
138
        messageserver *mockserver.MessageServer
139
}
140

141
// Deprecated: use NewAsynchronousPact
142
var NewMessagePact = NewAsynchronousPact
143

144
func NewAsynchronousPact(config Config) (*AsynchronousPact, error) {
×
145
        provider := &AsynchronousPact{
×
146
                config: config,
×
147
        }
×
148
        err := provider.validateConfig()
×
149

×
150
        if err != nil {
×
UNCOV
151
                return nil, err
×
152
        }
×
153

154
        native.Init(string(logging.LogLevel()))
×
UNCOV
155

×
UNCOV
156
        return provider, err
×
157
}
158

159
// validateConfig validates the configuration for the consumer test
160
func (p *AsynchronousPact) validateConfig() error {
×
161
        log.Println("[DEBUG] pact message validate config")
×
162
        dir, _ := os.Getwd()
×
163

×
164
        if p.config.PactDir == "" {
×
UNCOV
165
                p.config.PactDir = filepath.Join(dir, "pacts")
×
166
        }
×
167

168
        p.messageserver = mockserver.NewMessageServer(p.config.Consumer, p.config.Provider)
×
UNCOV
169
        p.messageserver.WithMetadata("pact-go", "version", strings.TrimPrefix(command.Version, "v"))
×
UNCOV
170

×
UNCOV
171
        return nil
×
172
}
173

174
// AddMessage creates a new asynchronous consumer expectation
175
// Deprecated: use AddAsynchronousMessage() instead
UNCOV
176
func (p *AsynchronousPact) AddMessage() *AsynchronousMessageBuilder {
×
UNCOV
177
        return p.AddAsynchronousMessage()
×
178
}
×
179

180
// AddMessage creates a new asynchronous consumer expectation
181
func (p *AsynchronousPact) AddAsynchronousMessage() *AsynchronousMessageBuilder {
×
182
        log.Println("[DEBUG] add message")
×
183

×
184
        message := p.messageserver.NewMessage()
×
185

×
186
        m := &AsynchronousMessageBuilder{
×
187
                messageHandle: message,
×
188
                messagePactV3: p,
×
189
        }
×
UNCOV
190

×
UNCOV
191
        return m
×
UNCOV
192
}
×
193

194
// VerifyMessageConsumerRaw creates a new Pact _message_ interaction to build a testable
195
// interaction.
196
//
197
//
198
// A Message Consumer is analagous to a Provider in the HTTP Interaction model.
199
// It is the receiver of an interaction, and needs to be able to handle whatever
200
// request was provided.
201
func (p *AsynchronousPact) verifyMessageConsumerRaw(messageToVerify *AsynchronousMessageBuilder, handler AsynchronousConsumer) error {
×
202
        log.Printf("[DEBUG] verify message")
×
203

×
204
        // 1. Strip out the matchers
×
205
        // Reify the message back to its "example/generated" form
×
206
        body, err := messageToVerify.messageHandle.GetMessageRequestContents()
×
207
        log.Println("[DEBUG] reified message raw", body)
×
UNCOV
208
        if err != nil {
×
209
                return fmt.Errorf("unexpected response from message server, this is a bug in the framework")
×
210
        }
×
211

212
        log.Println("[DEBUG] reified message raw", body)
×
213

×
214
        var m MessageContents
×
215
        // err = json.Unmarshal(body, &m)
×
216
        // if err != nil {
×
217
        //         return fmt.Errorf("unexpected response from message server, this is a bug in the framework")
×
218
        // }
×
219
        // log.Println("[DEBUG] unmarshalled into an AsynchronousMessage", m)
×
220

×
221
        // 2. Convert to an actual type (to avoid wrapping if needed/requested)
×
222
        // 3. Invoke the message handler
×
223
        // 4. write the pact file
×
224
        t := reflect.TypeOf(messageToVerify.Type)
×
225
        if t != nil && t.Name() != "interface" {
×
226
                // s, err := json.Marshal()
×
227
                // if err != nil {
×
228
                //         return fmt.Errorf("unable to generate message for type: %+v", messageToVerify.Type)
×
229
                // }
×
230
                err = json.Unmarshal(body, &messageToVerify.Type)
×
231

×
UNCOV
232
                if err != nil {
×
233
                        return fmt.Errorf("unable to narrow type to %v: %v", t.Name(), err)
×
UNCOV
234
                }
×
235

UNCOV
236
                m.Content = messageToVerify.Type
×
237
        }
238

239
        // TODO: extract metadata from FFI
240
        // m.Metadata =
241

242
        // Yield message, and send through handler function
243
        err = handler(m)
×
244

×
UNCOV
245
        if err != nil {
×
246
                return err
×
UNCOV
247
        }
×
248

UNCOV
249
        return p.messageserver.WritePactFile(p.config.PactDir, false)
×
250
}
251

252
// VerifyMessageConsumer is a test convience function for VerifyMessageConsumerRaw,
253
// accepting an instance of `*testing.T`
254
func (p *AsynchronousPact) Verify(t *testing.T, message *AsynchronousMessageBuilder, handler AsynchronousConsumer) error {
×
255
        err := p.verifyMessageConsumerRaw(message, handler)
×
256

×
UNCOV
257
        if err != nil {
×
258
                t.Errorf("VerifyMessageConsumer failed: %v", err)
×
UNCOV
259
        }
×
260

UNCOV
261
        return err
×
262
}
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