]> Cypherpunks.ru repositories - gostls13.git/blob - src/internal/trace/v2/testtrace/expectation.go
runtime: add execution tracer v2 behind GOEXPERIMENT=exectracer2
[gostls13.git] / src / internal / trace / v2 / testtrace / expectation.go
1 // Copyright 2023 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package testtrace
6
7 import (
8         "bufio"
9         "bytes"
10         "fmt"
11         "regexp"
12         "strconv"
13         "strings"
14 )
15
16 // Expectation represents the expected result of some operation.
17 type Expectation struct {
18         failure      bool
19         errorMatcher *regexp.Regexp
20 }
21
22 // ExpectSuccess returns an Expectation that trivially expects success.
23 func ExpectSuccess() *Expectation {
24         return new(Expectation)
25 }
26
27 // Check validates whether err conforms to the expectation. Returns
28 // an error if it does not conform.
29 //
30 // Conformance means that if failure is true, then err must be non-nil.
31 // If err is non-nil, then it must match errorMatcher.
32 func (e *Expectation) Check(err error) error {
33         if !e.failure && err != nil {
34                 return fmt.Errorf("unexpected error while reading the trace: %v", err)
35         }
36         if e.failure && err == nil {
37                 return fmt.Errorf("expected error while reading the trace: want something matching %q, got none", e.errorMatcher)
38         }
39         if e.failure && err != nil && !e.errorMatcher.MatchString(err.Error()) {
40                 return fmt.Errorf("unexpected error while reading the trace: want something matching %q, got %s", e.errorMatcher, err.Error())
41         }
42         return nil
43 }
44
45 // ParseExpectation parses the serialized form of an Expectation.
46 func ParseExpectation(data []byte) (*Expectation, error) {
47         exp := new(Expectation)
48         s := bufio.NewScanner(bytes.NewReader(data))
49         if s.Scan() {
50                 c := strings.SplitN(s.Text(), " ", 2)
51                 switch c[0] {
52                 case "SUCCESS":
53                 case "FAILURE":
54                         exp.failure = true
55                         if len(c) != 2 {
56                                 return exp, fmt.Errorf("bad header line for FAILURE: %q", s.Text())
57                         }
58                         matcher, err := parseMatcher(c[1])
59                         if err != nil {
60                                 return exp, err
61                         }
62                         exp.errorMatcher = matcher
63                 default:
64                         return exp, fmt.Errorf("bad header line: %q", s.Text())
65                 }
66                 return exp, nil
67         }
68         return exp, s.Err()
69 }
70
71 func parseMatcher(quoted string) (*regexp.Regexp, error) {
72         pattern, err := strconv.Unquote(quoted)
73         if err != nil {
74                 return nil, fmt.Errorf("malformed pattern: not correctly quoted: %s: %v", quoted, err)
75         }
76         matcher, err := regexp.Compile(pattern)
77         if err != nil {
78                 return nil, fmt.Errorf("malformed pattern: not a valid regexp: %s: %v", pattern, err)
79         }
80         return matcher, nil
81 }