| // 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 |
| } |