github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/testutil/paddedchecker.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2015-2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package testutil 21 22 import ( 23 "fmt" 24 "regexp" 25 "strings" 26 27 "gopkg.in/check.v1" 28 ) 29 30 type paddedChecker struct { 31 *check.CheckerInfo 32 isRegexp bool 33 isPartial bool 34 isLine bool 35 } 36 37 // EqualsPadded is a Checker that looks for an expected string to 38 // be equal to another except that the other might have been padded 39 // out to align with something else (so arbitrary amounts of 40 // horizontal whitespace is ok at the ends, and between non-whitespace 41 // bits). 42 var EqualsPadded = &paddedChecker{ 43 CheckerInfo: &check.CheckerInfo{Name: "EqualsPadded", Params: []string{"padded", "expected"}}, 44 isLine: true, 45 } 46 47 // MatchesPadded is a Checker that looks for an expected regexp in 48 // a string that might have been padded out to align with something 49 // else (so whitespace in the regexp is changed to [ \t]+, and ^[ \t]* 50 // is added to the beginning, and [ \t]*$ to the end of it). 51 var MatchesPadded = &paddedChecker{ 52 CheckerInfo: &check.CheckerInfo{Name: "MatchesPadded", Params: []string{"padded", "expected"}}, 53 isRegexp: true, 54 isLine: true, 55 } 56 57 // ContainsPadded is a Checker that looks for an expected string 58 // in another that might have been padded out to align with something 59 // else (so arbitrary amounts of horizontal whitespace is ok between 60 // non-whitespace bits). 61 var ContainsPadded = &paddedChecker{ 62 CheckerInfo: &check.CheckerInfo{Name: "ContainsPadded", Params: []string{"padded", "expected"}}, 63 isPartial: true, 64 isLine: true, 65 } 66 67 // EqualsWrapped is a Checker that looks for an expected string to be 68 // equal to another except that the other might have been padded out 69 // and wrapped (so arbitrary amounts of whitespace is ok at the ends, 70 // and between non-whitespace bits). 71 var EqualsWrapped = &paddedChecker{ 72 CheckerInfo: &check.CheckerInfo{Name: "EqualsWrapped", Params: []string{"wrapped", "expected"}}, 73 } 74 75 // MatchesWrapped is a Checker that looks for an expected regexp in a 76 // string that might have been padded and wrapped (so whitespace in 77 // the regexp is changed to \s+, and (?s)^\s* is added to the 78 // beginning, and \s*$ to the end of it). 79 var MatchesWrapped = &paddedChecker{ 80 CheckerInfo: &check.CheckerInfo{Name: "MatchesWrapped", Params: []string{"wrapped", "expected"}}, 81 isRegexp: true, 82 } 83 84 // ContainsWrapped is a Checker that looks for an expected string in 85 // another that might have been padded out and wrapped (so arbitrary 86 // amounts of whitespace is ok between non-whitespace bits). 87 var ContainsWrapped = &paddedChecker{ 88 CheckerInfo: &check.CheckerInfo{Name: "EqualsWrapped", Params: []string{"wrapped", "expected"}}, 89 isRegexp: false, 90 isPartial: true, 91 } 92 93 var spaceinator = regexp.MustCompile(`\s+`).ReplaceAllLiteralString 94 95 func (c *paddedChecker) Check(params []interface{}, names []string) (result bool, errstr string) { 96 var other string 97 switch v := params[0].(type) { 98 case string: 99 other = v 100 case []byte: 101 other = string(v) 102 case error: 103 if v != nil { 104 other = v.Error() 105 } 106 default: 107 return false, "left-hand value must be a string or []byte or error" 108 } 109 expected, ok := params[1].(string) 110 if !ok { 111 ebuf, ok := params[1].([]byte) 112 if !ok { 113 return false, "right-hand value must be a string or []byte" 114 } 115 expected = string(ebuf) 116 } 117 ws := `\s` 118 if c.isLine { 119 ws = `[\t ]` 120 } 121 if c.isRegexp { 122 _, err := regexp.Compile(expected) 123 if err != nil { 124 return false, fmt.Sprintf("right-hand value must be a valid regexp: %v", err) 125 } 126 expected = spaceinator(expected, ws+"+") 127 } else { 128 fields := strings.Fields(expected) 129 for i := range fields { 130 fields[i] = regexp.QuoteMeta(fields[i]) 131 } 132 expected = strings.Join(fields, ws+"+") 133 } 134 if !c.isPartial { 135 expected = "^" + ws + "*" + expected + ws + "*$" 136 } 137 if !c.isLine { 138 expected = "(?s)" + expected 139 } 140 141 matches, err := regexp.MatchString(expected, other) 142 if err != nil { 143 // can't happen (really) 144 panic(err) 145 } 146 return matches, "" 147 }