go.ligato.io/vpp-agent/v3@v3.5.0/plugins/linux/linuxmock/system_mock.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linuxmock 16 17 import ( 18 "os" 19 20 "github.com/vishvananda/netlink" 21 "github.com/vishvananda/netns" 22 ) 23 24 // SystemMock allows to mock netlink-related methods 25 type SystemMock struct { 26 responses []*WhenStResp 27 } 28 29 // NewSystemMock creates new instance of the mock and initializes response list 30 func NewSystemMock() *SystemMock { 31 return &SystemMock{ 32 responses: make([]*WhenStResp, 0), 33 } 34 } 35 36 // WhenStResp is helper struct with single method call and desired response items 37 type WhenStResp struct { 38 methodName string 39 items []interface{} 40 } 41 42 // When defines name of the related method. It creates a new instance of WhenStResp with provided method name and 43 // stores it to the mock. 44 func (mock *SystemMock) When(name string) *WhenStResp { 45 resp := &WhenStResp{ 46 methodName: name, 47 } 48 mock.responses = append(mock.responses, resp) 49 return resp 50 } 51 52 // ThenReturn receives array of items, which are desired to be returned in mocked method defined in "When". The full 53 // logic is: 54 // - When('someMethod').ThenReturn('values') 55 // 56 // Provided values should match return types of method. If method returns multiple values and only one is provided, 57 // mock tries to parse the value and returns it, while others will be nil or empty. 58 // 59 // If method is called several times, all cases must be defined separately, even if the return value is the same: 60 // - When('method1').ThenReturn('val1') 61 // - When('method1').ThenReturn('val1') 62 // 63 // All mocked methods are evaluated in same order they were assigned. 64 func (when *WhenStResp) ThenReturn(item ...interface{}) { 65 when.items = item 66 } 67 68 // Auxiliary method returns next return value for provided method as generic type 69 func (mock *SystemMock) getReturnValues(name string) (response []interface{}) { 70 for i, resp := range mock.responses { 71 if resp.methodName == name { 72 // Remove used response but retain order 73 mock.responses = append(mock.responses[:i], mock.responses[i+1:]...) 74 return resp.items 75 } 76 } 77 // Return empty response 78 return 79 } 80 81 // OpenFile implements OperatingSystem. 82 func (mock *SystemMock) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { 83 items := mock.getReturnValues("OpenFile") 84 if len(items) == 1 { 85 switch typed := items[0].(type) { 86 case *os.File: 87 return typed, nil 88 case error: 89 return nil, typed 90 } 91 } else if len(items) == 2 { 92 return items[0].(*os.File), items[1].(error) 93 } 94 return nil, nil 95 } 96 97 // MkDirAll implements OperatingSystem. 98 func (mock *SystemMock) MkDirAll(path string, perm os.FileMode) error { 99 items := mock.getReturnValues("MkDirAll") 100 if len(items) >= 1 { 101 return items[0].(error) 102 } 103 return nil 104 } 105 106 // Remove implements OperatingSystem. 107 func (mock *SystemMock) Remove(name string) error { 108 items := mock.getReturnValues("Remove") 109 if len(items) >= 1 { 110 return items[0].(error) 111 } 112 return nil 113 } 114 115 // Mount implements Syscall. 116 func (mock *SystemMock) Mount(source string, target string, fsType string, flags uintptr, data string) error { 117 items := mock.getReturnValues("Mount") 118 if len(items) >= 1 { 119 return items[0].(error) 120 } 121 return nil 122 } 123 124 // Unmount implements Syscall. 125 func (mock *SystemMock) Unmount(target string, flags int) error { 126 items := mock.getReturnValues("Unmount") 127 if len(items) >= 1 { 128 return items[0].(error) 129 } 130 return nil 131 } 132 133 // NewNetworkNamespace implements NetlinkNamespace. 134 func (mock *SystemMock) NewNetworkNamespace() (netns.NsHandle, error) { 135 items := mock.getReturnValues("NewNetworkNamespace") 136 if len(items) == 1 { 137 switch typed := items[0].(type) { 138 case netns.NsHandle: 139 return typed, nil 140 case error: 141 return 0, typed 142 } 143 } else if len(items) == 2 { 144 return items[0].(netns.NsHandle), items[1].(error) 145 } 146 return 0, nil 147 } 148 149 // GetNamespaceFromName implements NetNsNamespace. 150 func (mock *SystemMock) GetNamespaceFromName(name string) (netns.NsHandle, error) { 151 items := mock.getReturnValues("GetNamespaceFromName") 152 if len(items) == 1 { 153 switch typed := items[0].(type) { 154 case netns.NsHandle: 155 return typed, nil 156 case error: 157 return 0, typed 158 } 159 } else if len(items) == 2 { 160 return items[0].(netns.NsHandle), items[1].(error) 161 } 162 return 0, nil 163 } 164 165 // SetNamespace implements NetNsNamespace. 166 func (mock *SystemMock) SetNamespace(ns netns.NsHandle) error { 167 items := mock.getReturnValues("SetNamespace") 168 if len(items) >= 1 { 169 return items[0].(error) 170 } 171 return nil 172 } 173 174 // LinkSetNsFd implements NetlinkNamespace. 175 func (mock *SystemMock) LinkSetNsFd(link netlink.Link, fd int) error { 176 items := mock.getReturnValues("LinkSetNsFd") 177 if len(items) >= 1 { 178 return items[0].(error) 179 } 180 return nil 181 }