k8s.io/kubernetes@v1.29.3/pkg/kubelet/nodeshutdown/systemd/inhibit_linux_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2020 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package systemd 21 22 import ( 23 "context" 24 "fmt" 25 "testing" 26 "time" 27 28 "github.com/godbus/dbus/v5" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 type fakeDBusObject struct { 33 properties map[string]interface{} 34 bodyValue interface{} 35 } 36 37 func (obj *fakeDBusObject) Call(method string, flags dbus.Flags, args ...interface{}) *dbus.Call { 38 return &dbus.Call{Err: nil, Body: []interface{}{obj.bodyValue}} 39 } 40 41 func (obj *fakeDBusObject) CallWithContext(ctx context.Context, method string, flags dbus.Flags, args ...interface{}) *dbus.Call { 42 return nil 43 } 44 45 func (obj *fakeDBusObject) Go(method string, flags dbus.Flags, ch chan *dbus.Call, args ...interface{}) *dbus.Call { 46 return nil 47 } 48 49 func (obj *fakeDBusObject) GoWithContext(ctx context.Context, method string, flags dbus.Flags, ch chan *dbus.Call, args ...interface{}) *dbus.Call { 50 return nil 51 } 52 53 func (obj *fakeDBusObject) AddMatchSignal(iface, member string, options ...dbus.MatchOption) *dbus.Call { 54 return nil 55 } 56 57 func (obj *fakeDBusObject) RemoveMatchSignal(iface, member string, options ...dbus.MatchOption) *dbus.Call { 58 return nil 59 } 60 61 func (obj *fakeDBusObject) GetProperty(p string) (dbus.Variant, error) { 62 value, ok := obj.properties[p] 63 64 if !ok { 65 return dbus.Variant{}, fmt.Errorf("property %q does not exist in properties: %+v", p, obj.properties) 66 } 67 68 return dbus.MakeVariant(value), nil 69 } 70 71 func (obj *fakeDBusObject) SetProperty(p string, v interface{}) error { 72 return nil 73 } 74 75 func (obj *fakeDBusObject) StoreProperty(p string, v interface{}) error { 76 return nil 77 } 78 79 func (obj *fakeDBusObject) Destination() string { 80 return "" 81 } 82 83 func (obj *fakeDBusObject) Path() dbus.ObjectPath { 84 return "" 85 } 86 87 type fakeSystemDBus struct { 88 fakeDBusObject *fakeDBusObject 89 signalChannel chan<- *dbus.Signal 90 } 91 92 func (f *fakeSystemDBus) Object(dest string, path dbus.ObjectPath) dbus.BusObject { 93 return f.fakeDBusObject 94 } 95 96 func (f *fakeSystemDBus) Signal(ch chan<- *dbus.Signal) { 97 f.signalChannel = ch 98 } 99 100 func (f *fakeSystemDBus) AddMatchSignal(options ...dbus.MatchOption) error { 101 return nil 102 } 103 104 func TestCurrentInhibitDelay(t *testing.T) { 105 thirtySeconds := time.Duration(30) * time.Second 106 107 bus := DBusCon{ 108 SystemBus: &fakeSystemDBus{ 109 fakeDBusObject: &fakeDBusObject{ 110 properties: map[string]interface{}{ 111 "org.freedesktop.login1.Manager.InhibitDelayMaxUSec": uint64(thirtySeconds / time.Microsecond), 112 }, 113 }, 114 }, 115 } 116 117 delay, err := bus.CurrentInhibitDelay() 118 assert.NoError(t, err) 119 assert.Equal(t, thirtySeconds, delay) 120 } 121 122 func TestInhibitShutdown(t *testing.T) { 123 var fakeFd uint32 = 42 124 125 bus := DBusCon{ 126 SystemBus: &fakeSystemDBus{ 127 fakeDBusObject: &fakeDBusObject{ 128 bodyValue: fakeFd, 129 }, 130 }, 131 } 132 133 fdLock, err := bus.InhibitShutdown() 134 assert.Equal(t, InhibitLock(fakeFd), fdLock) 135 assert.NoError(t, err) 136 } 137 138 func TestReloadLogindConf(t *testing.T) { 139 bus := DBusCon{ 140 SystemBus: &fakeSystemDBus{ 141 fakeDBusObject: &fakeDBusObject{}, 142 }, 143 } 144 assert.NoError(t, bus.ReloadLogindConf()) 145 } 146 147 func TestMonitorShutdown(t *testing.T) { 148 var tests = []struct { 149 desc string 150 shutdownActive bool 151 }{ 152 { 153 desc: "shutdown is active", 154 shutdownActive: true, 155 }, 156 { 157 desc: "shutdown is not active", 158 shutdownActive: false, 159 }, 160 } 161 162 for _, tc := range tests { 163 tc := tc 164 t.Run(tc.desc, func(t *testing.T) { 165 fakeSystemBus := &fakeSystemDBus{} 166 bus := DBusCon{ 167 SystemBus: fakeSystemBus, 168 } 169 170 outChan, err := bus.MonitorShutdown() 171 assert.NoError(t, err) 172 173 done := make(chan bool) 174 175 go func() { 176 select { 177 case res := <-outChan: 178 assert.Equal(t, tc.shutdownActive, res) 179 done <- true 180 case <-time.After(5 * time.Second): 181 t.Errorf("Timed out waiting for shutdown message") 182 done <- true 183 } 184 }() 185 186 signal := &dbus.Signal{Body: []interface{}{tc.shutdownActive}} 187 fakeSystemBus.signalChannel <- signal 188 <-done 189 }) 190 } 191 }