github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/testutil/symlinktargetchecker.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 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 "os" 25 "regexp" 26 "strings" 27 28 "gopkg.in/check.v1" 29 ) 30 31 type symlinkTargetChecker struct { 32 *check.CheckerInfo 33 exact bool 34 } 35 36 // SymlinkTargetEquals verifies that the given file is a symbolic link with the given target. 37 var SymlinkTargetEquals check.Checker = &symlinkTargetChecker{ 38 CheckerInfo: &check.CheckerInfo{Name: "SymlinkTargetEquals", Params: []string{"filename", "target"}}, 39 exact: true, 40 } 41 42 // SymlinkTargetContains verifies that the given file is a symbolic link whose target contains the provided text. 43 var SymlinkTargetContains check.Checker = &symlinkTargetChecker{ 44 CheckerInfo: &check.CheckerInfo{Name: "SymlinkTargetContains", Params: []string{"filename", "target"}}, 45 } 46 47 // SymlinkTargetMatches verifies that the given file is a symbolic link whose target matches the provided regular expression. 48 var SymlinkTargetMatches check.Checker = &symlinkTargetChecker{ 49 CheckerInfo: &check.CheckerInfo{Name: "SymlinkTargetMatches", Params: []string{"filename", "regex"}}, 50 } 51 52 func (c *symlinkTargetChecker) Check(params []interface{}, names []string) (result bool, error string) { 53 filename, ok := params[0].(string) 54 if !ok { 55 return false, "Filename must be a string" 56 } 57 if names[1] == "regex" { 58 regexpr, ok := params[1].(string) 59 if !ok { 60 return false, "Regex must be a string" 61 } 62 rx, err := regexp.Compile(regexpr) 63 if err != nil { 64 return false, fmt.Sprintf("Cannot compile regexp %q: %v", regexpr, err) 65 } 66 params[1] = rx 67 } 68 return symlinkTargetCheck(filename, params[1], c.exact) 69 } 70 71 func symlinkTargetCheck(filename string, expectedTarget interface{}, exact bool) (result bool, error string) { 72 target, err := os.Readlink(filename) 73 if err != nil { 74 return false, fmt.Sprintf("Cannot read symbolic link: %v", err) 75 } 76 if exact { 77 switch expectedTarget := expectedTarget.(type) { 78 case string: 79 result = target == expectedTarget 80 default: 81 error = fmt.Sprintf("Cannot compare symbolic link target with something of type %T", expectedTarget) 82 } 83 } else { 84 switch expectedTarget := expectedTarget.(type) { 85 case string: 86 result = strings.Contains(target, expectedTarget) 87 case *regexp.Regexp: 88 result = expectedTarget.MatchString(target) 89 default: 90 error = fmt.Sprintf("Cannot compare symbolic link target with something of type %T", expectedTarget) 91 } 92 } 93 if !result { 94 if error == "" { 95 error = fmt.Sprintf("Failed to match with symbolic link target:\n%v", target) 96 } 97 return result, error 98 } 99 return result, "" 100 }