PerformFuzzyMatch performs fuzzy matching on the request body. Noisy (obfuscated) values are stripped from mock bodies before computing similarity so that redacted padding doesn't skew the score.
(tcsMocks []*models.Mock, reqBuff []byte)
| 826 | // Noisy (obfuscated) values are stripped from mock bodies before computing |
| 827 | // similarity so that redacted padding doesn't skew the score. |
| 828 | func (h *HTTP) PerformFuzzyMatch(tcsMocks []*models.Mock, reqBuff []byte) (bool, *models.Mock) { |
| 829 | // Log all mock names in a single line for better readability |
| 830 | mockNames := make([]string, len(tcsMocks)) |
| 831 | for i, mock := range tcsMocks { |
| 832 | mockNames[i] = mock.Name |
| 833 | } |
| 834 | h.Logger.Debug("mocks under consideration for performfuzzyMatch function", zap.Strings("mock names", mockNames)) |
| 835 | |
| 836 | encodedReq := encode(reqBuff) |
| 837 | for _, mock := range tcsMocks { |
| 838 | encodedMock, _ := decode(mock.Spec.HTTPReq.Body) |
| 839 | if string(encodedMock) == string(reqBuff) || mock.Spec.HTTPReq.Body == encodedReq { |
| 840 | h.Logger.Debug("http mock matched", |
| 841 | zap.String("mock", mock.Name), |
| 842 | zap.Float64("match_percentage", 100.0), |
| 843 | zap.String("match_type", "fuzzy_exact")) |
| 844 | return true, mock |
| 845 | } |
| 846 | } |
| 847 | |
| 848 | // Build mock body strings, stripping noisy values for fair comparison |
| 849 | mockStrings := make([]string, len(tcsMocks)) |
| 850 | for i := range tcsMocks { |
| 851 | nc := util.NewNoiseChecker(tcsMocks[i].Noise) |
| 852 | mockStrings[i] = util.StripNoisyJSON(tcsMocks[i].Spec.HTTPReq.Body, nc) |
| 853 | } |
| 854 | |
| 855 | // String-based fuzzy matching (Levenshtein distance) |
| 856 | reqStr := string(reqBuff) |
| 857 | if util.IsASCII(reqStr) { |
| 858 | idx, dist := h.findStringMatch(reqStr, mockStrings) |
| 859 | if idx != -1 { |
| 860 | maxLen := len(reqStr) |
| 861 | if len(mockStrings[idx]) > maxLen { |
| 862 | maxLen = len(mockStrings[idx]) |
| 863 | } |
| 864 | pct := 0.0 |
| 865 | if maxLen > 0 { |
| 866 | pct = (1.0 - float64(dist)/float64(maxLen)) * 100 |
| 867 | } |
| 868 | h.Logger.Debug("http mock matched", |
| 869 | zap.String("mock", tcsMocks[idx].Name), |
| 870 | zap.Float64("match_percentage", pct), |
| 871 | zap.String("match_type", "fuzzy_levenshtein")) |
| 872 | return true, tcsMocks[idx] |
| 873 | } |
| 874 | } |
| 875 | |
| 876 | // Binary fuzzy matching (Jaccard similarity) with stripped mock bodies |
| 877 | mockBodies := make([][]byte, len(mockStrings)) |
| 878 | for i := range mockStrings { |
| 879 | mockBodies[i] = []byte(mockStrings[i]) |
| 880 | } |
| 881 | mxIdx, mxSim := h.jaccardBestMatch(mockBodies, reqBuff) |
| 882 | if mxIdx != -1 { |
| 883 | h.Logger.Debug("http mock matched", |
| 884 | zap.String("mock", tcsMocks[mxIdx].Name), |
| 885 | zap.Float64("match_percentage", mxSim*100), |
no test coverage detected