expectation.mx raw
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 )
14
15 // Expectation represents the expected result of some operation.
16 type Expectation struct {
17 failure bool
18 errorMatcher *regexp.Regexp
19 }
20
21 // ExpectSuccess returns an Expectation that trivially expects success.
22 func ExpectSuccess() *Expectation {
23 return &Expectation{}
24 }
25
26 // Check validates whether err conforms to the expectation. Returns
27 // an error if it does not conform.
28 //
29 // Conformance means that if failure is true, then err must be non-nil.
30 // If err is non-nil, then it must match errorMatcher.
31 func (e *Expectation) Check(err error) error {
32 if !e.failure && err != nil {
33 return fmt.Errorf("unexpected error while reading the trace: %v", err)
34 }
35 if e.failure && err == nil {
36 return fmt.Errorf("expected error while reading the trace: want something matching %q, got none", e.errorMatcher)
37 }
38 if e.failure && err != nil && !e.errorMatcher.MatchString(err.Error()) {
39 return fmt.Errorf("unexpected error while reading the trace: want something matching %q, got %s", e.errorMatcher, err.Error())
40 }
41 return nil
42 }
43
44 // ParseExpectation parses the serialized form of an Expectation.
45 func ParseExpectation(data []byte) (*Expectation, error) {
46 exp := &Expectation{}
47 s := bufio.NewScanner(bytes.NewReader(data))
48 if s.Scan() {
49 c := bytes.SplitN(s.Text(), " ", 2)
50 switch c[0] {
51 case "SUCCESS":
52 case "FAILURE":
53 exp.failure = true
54 if len(c) != 2 {
55 return exp, fmt.Errorf("bad header line for FAILURE: %q", s.Text())
56 }
57 matcher, err := parseMatcher(c[1])
58 if err != nil {
59 return exp, err
60 }
61 exp.errorMatcher = matcher
62 default:
63 return exp, fmt.Errorf("bad header line: %q", s.Text())
64 }
65 return exp, nil
66 }
67 return exp, s.Err()
68 }
69
70 func parseMatcher(quoted []byte) (*regexp.Regexp, error) {
71 pattern, err := strconv.Unquote(quoted)
72 if err != nil {
73 return nil, fmt.Errorf("malformed pattern: not correctly quoted: %s: %v", quoted, err)
74 }
75 matcher, err := regexp.Compile(pattern)
76 if err != nil {
77 return nil, fmt.Errorf("malformed pattern: not a valid regexp: %s: %v", pattern, err)
78 }
79 return matcher, nil
80 }
81