github.com/yandex/pandora@v0.5.32/components/providers/scenario/http/postprocessor/assert_response.go (about)

     1  package postprocessor
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"strings"
     9  )
    10  
    11  type errAssert struct {
    12  	pattern string
    13  	t       string
    14  }
    15  
    16  func (e *errAssert) Error() string {
    17  	return "assert failed: " + e.t + " does not contain " + e.pattern
    18  }
    19  
    20  type AssertSize struct {
    21  	Val int
    22  	Op  string
    23  }
    24  
    25  type AssertResponse struct {
    26  	Headers    map[string]string
    27  	Body       []string
    28  	StatusCode int `config:"status_code"`
    29  	Size       *AssertSize
    30  }
    31  
    32  func (a AssertResponse) Process(resp *http.Response, body io.Reader) (map[string]any, error) {
    33  	var b []byte
    34  	var err error
    35  	if len(a.Body) > 0 && body != nil {
    36  		b, err = io.ReadAll(body)
    37  		if err != nil {
    38  			return nil, fmt.Errorf("cant read body: %w", err)
    39  		}
    40  	}
    41  	for _, v := range a.Body {
    42  		if !bytes.Contains(b, []byte(v)) {
    43  			return nil, &errAssert{pattern: v, t: "body"}
    44  		}
    45  	}
    46  	for k, v := range a.Headers {
    47  		if !(strings.Contains(resp.Header.Get(k), v)) {
    48  			return nil, &errAssert{pattern: v, t: "header " + k}
    49  		}
    50  	}
    51  	if a.StatusCode != 0 && a.StatusCode != resp.StatusCode {
    52  		return nil, &errAssert{
    53  			pattern: fmt.Sprintf("expect code %d, recieve code %d", a.StatusCode, resp.StatusCode),
    54  			t:       "code",
    55  		}
    56  	}
    57  	if a.Size != nil {
    58  		pattern := fmt.Sprintf("expect size %d %s %d", a.Size.Val, a.Size.Op, len(b))
    59  		switch a.Size.Op {
    60  		case "eq", "=":
    61  			if a.Size.Val != len(b) {
    62  				return nil, &errAssert{
    63  					pattern: pattern,
    64  					t:       "size",
    65  				}
    66  			}
    67  		case "lt", "<":
    68  			if a.Size.Val < len(b) {
    69  				return nil, &errAssert{
    70  					pattern: pattern,
    71  					t:       "size",
    72  				}
    73  			}
    74  		case "gt", ">":
    75  			if a.Size.Val > len(b) {
    76  				return nil, &errAssert{
    77  					pattern: pattern,
    78  					t:       "size",
    79  				}
    80  			}
    81  		default:
    82  			return nil, fmt.Errorf("unknown op %s", a.Size.Op)
    83  		}
    84  	}
    85  
    86  	return nil, nil
    87  }
    88  
    89  func (a AssertResponse) Validate() error {
    90  	if a.Size != nil {
    91  		if a.Size.Val < 0 {
    92  			return fmt.Errorf("size must be positive")
    93  		}
    94  		if a.Size.Op != "eq" && a.Size.Op != "=" && a.Size.Op != "lt" && a.Size.Op != "<" && a.Size.Op != "gt" && a.Size.Op != ">" {
    95  			return fmt.Errorf("assert/response validation unknown op %s", a.Size.Op)
    96  		}
    97  	}
    98  	return nil
    99  }