dsl/client.go
func (p *PactClient) VerifyProvider(request types.VerifyRequest) (types.ProviderVerifierResponse, error) {
	log.Println("[DEBUG] client: verifying a provider")
	var response types.ProviderVerifierResponse

	// Convert request into flags, and validate request
	err := request.Validate()
	if err != nil {
		return response, err
	}

	address := getAddress(request.ProviderBaseURL)
	port := getPort(request.ProviderBaseURL)

	waitForPort(port, p.getNetworkInterface(), address, p.TimeoutDuration,
		fmt.Sprintf(`Timed out waiting for Provider API to start on port %d - are you sure it's running?`, port))

	// Run command, splitting out stderr and stdout. The command can fail for
	// several reasons:
	// 1. Command is unable to run at all.
	// 2. Command runs, but fails for unknown reason.
	// 3. Command runs, and returns exit status 1 because the tests fail.
	//
	// First, attempt to decode the response of the stdout.
	// If that is successful, we are at case 3. Return stdout as message, no error.
	// Else, return an error, include stderr and stdout in both the error and message.
	svc := p.verificationSvcManager.NewService(request.Args)
	cmd := svc.Command()

	stdOutPipe, err := cmd.StdoutPipe()
	if err != nil {
		return response, err
	}
	stdErrPipe, err := cmd.StderrPipe()
	if err != nil {
		return response, err
	}
	err = cmd.Start()
	if err != nil {
		return response, err
	}
	stdOut, err := ioutil.ReadAll(stdOutPipe)
	if err != nil {
		return response, err
	}
	stdErr, err := ioutil.ReadAll(stdErrPipe)
	if err != nil {
		return response, err
	}

	err = cmd.Wait()

	// Split by lines, as the content is now JSONL
	// See https://github.com/pact-foundation/pact-go/issues/88#issuecomment-404686337
	verifications := strings.Split(string(stdOut), "\n")

	var verification types.ProviderVerifierResponse
	for _, v := range verifications {
		v = strings.TrimSpace(v)

		// TODO: fix once https://github.com/pact-foundation/pact-provider-verifier/issues/26
		//       is addressed
		// logging to stdout breaks the JSON response
		// https://github.com/pact-foundation/pact-ruby/commit/06fa61581512ba5570c315d089f2c0fc23c8cb11
		if v != "" && strings.Index(v, "INFO") != 0 {
			dErr := json.Unmarshal([]byte(v), &verification)

			response.Examples = append(response.Examples, verification.Examples...)

			if dErr != nil {
				err = dErr
			}
		}
	}

	if err == nil {
		return response, err
	}

	return response, fmt.Errorf("error verifying provider: %s\n\nSTDERR:\n%s\n\nSTDOUT:\n%s", err, stdErr, stdOut)
}
func (p *PactClient) VerifyProvider(request types.VerifyRequest) (types.ProviderVerifierResponse, error) {
	log.Println("[DEBUG] client: verifying a provider")
	var response types.ProviderVerifierResponse

	// Convert request into flags, and validate request
	err := request.Validate()
	if err != nil {
		return response, err
	}

	address := getAddress(request.ProviderBaseURL)
	port := getPort(request.ProviderBaseURL)

	waitForPort(port, p.getNetworkInterface(), address, p.TimeoutDuration,
		fmt.Sprintf(`Timed out waiting for Provider API to start on port %d - are you sure it's running?`, port))

	// Run command, splitting out stderr and stdout. The command can fail for
	// several reasons:
	// 1. Command is unable to run at all.
	// 2. Command runs, but fails for unknown reason.
	// 3. Command runs, and returns exit status 1 because the tests fail.
	//
	// First, attempt to decode the response of the stdout.
	// If that is successful, we are at case 3. Return stdout as message, no error.
	// Else, return an error, include stderr and stdout in both the error and message.
	svc := p.verificationSvcManager.NewService(request.Args)
	cmd := svc.Command()

	stdOutPipe, err := cmd.StdoutPipe()
	if err != nil {
		return response, err
	}
	stdErrPipe, err := cmd.StderrPipe()
	if err != nil {
		return response, err
	}
	err = cmd.Start()
	if err != nil {
		return response, err
	}
	stdOut, err := ioutil.ReadAll(stdOutPipe)
	if err != nil {
		return response, err
	}
	stdErr, err := ioutil.ReadAll(stdErrPipe)
	if err != nil {
		return response, err
	}

	err = cmd.Wait()

	// Split by lines, as the content is now JSONL
	// See https://github.com/pact-foundation/pact-go/issues/88#issuecomment-404686337
	verifications := strings.Split(string(stdOut), "\n")

	var verification types.ProviderVerifierResponse
	for _, v := range verifications {
		v = strings.TrimSpace(v)

		// TODO: fix once https://github.com/pact-foundation/pact-provider-verifier/issues/26
		//       is addressed
		// logging to stdout breaks the JSON response
		// https://github.com/pact-foundation/pact-ruby/commit/06fa61581512ba5570c315d089f2c0fc23c8cb11
		if v != "" && strings.Index(v, "INFO") != 0 {
			dErr := json.Unmarshal([]byte(v), &verification)

			response.Examples = append(response.Examples, verification.Examples...)

			if dErr != nil {
				err = dErr
			}
		}
	}

	if err == nil {
		return response, err
	}

	return response, fmt.Errorf("error verifying provider: %s\n\nSTDERR:\n%s\n\nSTDOUT:\n%s", err, stdErr, stdOut)
}
// VerifyProvider runs the verification process against a running Provider.
// TODO: extract/refactor the stdout/error streaems from these functions