github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/testutil/syscallschecker.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 "reflect" 25 26 "gopkg.in/check.v1" 27 ) 28 29 type syscallsEqualChecker struct { 30 *check.CheckerInfo 31 } 32 33 // SyscallsEqual checks that one sequence of system calls is equal to another. 34 var SyscallsEqual check.Checker = &syscallsEqualChecker{ 35 CheckerInfo: &check.CheckerInfo{Name: "SyscallsEqual", Params: []string{"actualList", "expectedList"}}, 36 } 37 38 func (c *syscallsEqualChecker) Check(params []interface{}, names []string) (result bool, error string) { 39 actualList, ok := params[0].([]CallResultError) 40 if !ok { 41 return false, "left-hand-side argument must be of type []CallResultError" 42 } 43 expectedList, ok := params[1].([]CallResultError) 44 if !ok { 45 return false, "right-hand-side argument must be of type []CallResultError" 46 } 47 48 for i, actual := range actualList { 49 if i >= len(expectedList) { 50 return false, fmt.Sprintf("system call #%d %#q unexpectedly present, got %d system call(s) but expected only %d", 51 i, actual.C, len(actualList), len(expectedList)) 52 } 53 expected := expectedList[i] 54 if actual.C != expected.C { 55 return false, fmt.Sprintf("system call #%d differs in operation, actual %#q, expected %#q", i, actual.C, expected.C) 56 } 57 if !reflect.DeepEqual(actual, expected) { 58 switch { 59 case actual.E == nil && expected.E == nil && !reflect.DeepEqual(actual.R, expected.R): 60 // The call succeeded but not like we expected. 61 return false, fmt.Sprintf("system call #%d %#q differs in result, actual: %#v, expected: %#v", 62 i, actual.C, actual.R, expected.R) 63 case actual.E != nil && expected.E != nil && !reflect.DeepEqual(actual.E, expected.E): 64 // The call failed but not like we expected. 65 return false, fmt.Sprintf("system call #%d %#q differs in error, actual: %s, expected: %s", 66 i, actual.C, actual.E, expected.E) 67 case actual.E != nil && expected.E == nil && expected.R == nil: 68 // The call failed but we expected it to succeed. 69 return false, fmt.Sprintf("system call #%d %#q unexpectedly failed, actual error: %s", i, actual.C, actual.E) 70 case actual.E != nil && expected.E == nil && expected.R != nil: 71 // The call failed but we expected it to succeed with some result. 72 return false, fmt.Sprintf("system call #%d %#q unexpectedly failed, actual error: %s, expected result: %#v", i, actual.C, actual.E, expected.R) 73 case actual.E == nil && expected.E != nil && actual.R == nil: 74 // The call succeeded with some result but we expected it to fail. 75 return false, fmt.Sprintf("system call #%d %#q unexpectedly succeeded, expected error: %s", i, actual.C, expected.E) 76 case actual.E == nil && expected.E != nil && actual.R != nil: 77 // The call succeeded but we expected it to fail. 78 return false, fmt.Sprintf("system call #%d %#q unexpectedly succeeded, actual result: %#v, expected error: %s", i, actual.C, actual.R, expected.E) 79 default: 80 panic("unexpected call-result-error case") 81 } 82 } 83 } 84 if len(actualList) < len(expectedList) && len(expectedList) > 0 { 85 return false, fmt.Sprintf("system call #%d %#q unexpectedly absent, got only %d system call(s) but expected %d", 86 len(actualList), expectedList[len(actualList)].C, len(actualList), len(expectedList)) 87 } 88 return true, "" 89 }