| // Copyright 2023 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package testtrace | |
| import ( | |
| "bufio" | |
| "bytes" | |
| "fmt" | |
| "regexp" | |
| "strconv" | |
| "strings" | |
| ) | |
| // Expectation represents the expected result of some operation. | |
| type Expectation struct { | |
| failure bool | |
| errorMatcher *regexp.Regexp | |
| } | |
| // ExpectSuccess returns an Expectation that trivially expects success. | |
| func ExpectSuccess() *Expectation { | |
| return new(Expectation) | |
| } | |
| // Check validates whether err conforms to the expectation. Returns | |
| // an error if it does not conform. | |
| // | |
| // Conformance means that if failure is true, then err must be non-nil. | |
| // If err is non-nil, then it must match errorMatcher. | |
| func (e *Expectation) Check(err error) error { | |
| if !e.failure && err != nil { | |
| return fmt.Errorf("unexpected error while reading the trace: %v", err) | |
| } | |
| if e.failure && err == nil { | |
| return fmt.Errorf("expected error while reading the trace: want something matching %q, got none", e.errorMatcher) | |
| } | |
| if e.failure && err != nil && !e.errorMatcher.MatchString(err.Error()) { | |
| return fmt.Errorf("unexpected error while reading the trace: want something matching %q, got %s", e.errorMatcher, err.Error()) | |
| } | |
| return nil | |
| } | |
| // ParseExpectation parses the serialized form of an Expectation. | |
| func ParseExpectation(data []byte) (*Expectation, error) { | |
| exp := new(Expectation) | |
| s := bufio.NewScanner(bytes.NewReader(data)) | |
| if s.Scan() { | |
| c := strings.SplitN(s.Text(), " ", 2) | |
| switch c[0] { | |
| case "SUCCESS": | |
| case "FAILURE": | |
| exp.failure = true | |
| if len(c) != 2 { | |
| return exp, fmt.Errorf("bad header line for FAILURE: %q", s.Text()) | |
| } | |
| matcher, err := parseMatcher(c[1]) | |
| if err != nil { | |
| return exp, err | |
| } | |
| exp.errorMatcher = matcher | |
| default: | |
| return exp, fmt.Errorf("bad header line: %q", s.Text()) | |
| } | |
| return exp, nil | |
| } | |
| return exp, s.Err() | |
| } | |
| func parseMatcher(quoted string) (*regexp.Regexp, error) { | |
| pattern, err := strconv.Unquote(quoted) | |
| if err != nil { | |
| return nil, fmt.Errorf("malformed pattern: not correctly quoted: %s: %v", quoted, err) | |
| } | |
| matcher, err := regexp.Compile(pattern) | |
| if err != nil { | |
| return nil, fmt.Errorf("malformed pattern: not a valid regexp: %s: %v", pattern, err) | |
| } | |
| return matcher, nil | |
| } |