MCPcopy
hub / github.com/keploy/keploy / compareMultipartStream

Function compareMultipartStream

pkg/util.go:1667–1743  ·  view source on GitHub ↗
(expectedResp models.HTTPResp, stream io.Reader, boundary string, jsonNoiseKeys map[string]struct{}, logger *zap.Logger)

Source from the content-addressed store, hash-verified

1665}
1666
1667func compareMultipartStream(expectedResp models.HTTPResp, stream io.Reader, boundary string, jsonNoiseKeys map[string]struct{}, logger *zap.Logger) (bool, string, *StreamMismatchInfo, error) {
1668 if strings.TrimSpace(boundary) == "" {
1669 return false, "", nil, fmt.Errorf("missing multipart boundary for stream comparison")
1670 }
1671
1672 expectedBody := expectedResp.Body
1673 expectedQueue, err := parseMultipartQueue(strings.NewReader(expectedBody), boundary)
1674 if err != nil {
1675 return false, "", nil, err
1676 }
1677
1678 actualQueue := make([]string, 0, len(expectedQueue))
1679 nextExpected := 0
1680 reader := multipart.NewReader(stream, boundary)
1681
1682 for {
1683 part, partErr := reader.NextPart()
1684 if partErr == io.EOF {
1685 break
1686 }
1687 if partErr != nil {
1688 return false, strings.Join(actualQueue, "\n\n--PART--\n\n"), nil, partErr
1689 }
1690
1691 actualPart, partReadErr := readMultipartPart(part)
1692 _ = part.Close()
1693 if partReadErr != nil {
1694 return false, strings.Join(actualQueue, "\n\n--PART--\n\n"), nil, partReadErr
1695 }
1696
1697 if nextExpected >= len(expectedQueue) {
1698 logger.Debug("received additional multipart stream data after expected stream was fully matched; closing stream capture",
1699 zap.Int("expected_parts", len(expectedQueue)))
1700 break
1701 }
1702
1703 expected := expectedQueue[nextExpected]
1704 actualQueue = append(actualQueue, actualPart.describe())
1705 ok, reason := compareMultipartPart(expected, actualPart, jsonNoiseKeys)
1706 if !ok {
1707 logger.Debug("multipart stream mismatch",
1708 zap.Int("part_index", nextExpected),
1709 zap.String("reason", reason),
1710 zap.String("expected_part", expected.describe()),
1711 zap.String("actual_part", actualPart.describe()))
1712 mismatchInfo := &StreamMismatchInfo{
1713 FrameIndex: nextExpected,
1714 ExpectedFrame: expected.describe(),
1715 ActualFrame: actualPart.describe(),
1716 Reason: reason,
1717 }
1718 return false, strings.Join(actualQueue, "\n\n--PART--\n\n"), mismatchInfo, nil
1719 }
1720
1721 nextExpected++
1722 if nextExpected == len(expectedQueue) {
1723 logger.Debug("all expected multipart parts matched; closing stream capture early to avoid waiting for extra stream parts",
1724 zap.Int("matched_parts", nextExpected))

Callers 1

CompareHTTPStreamFunction · 0.85

Calls 7

parseMultipartQueueFunction · 0.85
readMultipartPartFunction · 0.85
compareMultipartPartFunction · 0.85
describeMethod · 0.80
CloseMethod · 0.65
DebugMethod · 0.65
StringMethod · 0.45

Tested by

no test coverage detected