github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/testutil/filecontentchecker.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 "bytes" 24 "fmt" 25 "io/ioutil" 26 "regexp" 27 "strings" 28 29 "gopkg.in/check.v1" 30 ) 31 32 type fileContentChecker struct { 33 *check.CheckerInfo 34 exact bool 35 } 36 37 // FileEquals verifies that the given file's content is equal to the string (or 38 // fmt.Stringer), []byte provided, or the contents referred by a FileContentRef. 39 var FileEquals check.Checker = &fileContentChecker{ 40 CheckerInfo: &check.CheckerInfo{Name: "FileEquals", Params: []string{"filename", "contents"}}, 41 exact: true, 42 } 43 44 // FileContains verifies that the given file's content contains 45 // the string (or fmt.Stringer) or []byte provided. 46 var FileContains check.Checker = &fileContentChecker{ 47 CheckerInfo: &check.CheckerInfo{Name: "FileContains", Params: []string{"filename", "contents"}}, 48 } 49 50 // FileMatches verifies that the given file's content matches 51 // the string provided. 52 var FileMatches check.Checker = &fileContentChecker{ 53 CheckerInfo: &check.CheckerInfo{Name: "FileMatches", Params: []string{"filename", "regex"}}, 54 } 55 56 // FileContentRef refers to the content of file by its name, to use in 57 // conjunction with FileEquals. 58 type FileContentRef string 59 60 func (c *fileContentChecker) Check(params []interface{}, names []string) (result bool, error string) { 61 filename, ok := params[0].(string) 62 if !ok { 63 return false, "Filename must be a string" 64 } 65 if names[1] == "regex" { 66 regexpr, ok := params[1].(string) 67 if !ok { 68 return false, "Regex must be a string" 69 } 70 rx, err := regexp.Compile(regexpr) 71 if err != nil { 72 return false, fmt.Sprintf("Cannot compile regexp %q: %v", regexpr, err) 73 } 74 params[1] = rx 75 } 76 return fileContentCheck(filename, params[1], c.exact) 77 } 78 79 func fileContentCheck(filename string, content interface{}, exact bool) (result bool, error string) { 80 buf, err := ioutil.ReadFile(filename) 81 if err != nil { 82 return false, fmt.Sprintf("Cannot read file %q: %v", filename, err) 83 } 84 presentableBuf := string(buf) 85 if exact { 86 switch content := content.(type) { 87 case string: 88 result = presentableBuf == content 89 case []byte: 90 result = bytes.Equal(buf, content) 91 presentableBuf = "<binary data>" 92 case fmt.Stringer: 93 result = presentableBuf == content.String() 94 case FileContentRef: 95 referenceFilename := string(content) 96 reference, err := ioutil.ReadFile(referenceFilename) 97 if err != nil { 98 return false, fmt.Sprintf("Cannot read reference file %q: %v", referenceFilename, err) 99 } 100 result = bytes.Equal(buf, reference) 101 if !result { 102 error = fmt.Sprintf("Failed to match contents with reference file %q:\n%v", referenceFilename, presentableBuf) 103 } 104 105 default: 106 error = fmt.Sprintf("Cannot compare file contents with something of type %T", content) 107 } 108 } else { 109 switch content := content.(type) { 110 case string: 111 result = strings.Contains(presentableBuf, content) 112 case []byte: 113 result = bytes.Contains(buf, content) 114 presentableBuf = "<binary data>" 115 case *regexp.Regexp: 116 result = content.Match(buf) 117 case fmt.Stringer: 118 result = strings.Contains(presentableBuf, content.String()) 119 case FileContentRef: 120 error = "Non-exact match with reference file is not supported" 121 default: 122 error = fmt.Sprintf("Cannot compare file contents with something of type %T", content) 123 } 124 } 125 if !result { 126 if error == "" { 127 error = fmt.Sprintf("Failed to match with file contents:\n%v", presentableBuf) 128 } 129 return result, error 130 } 131 return result, "" 132 }