github.com/HACKERALERT/Picocrypt/src/external/sys@v0.0.0-20210609020157-e519952f829f/windows/svc/mgr/mgr_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build windows 6 7 package mgr_test 8 9 import ( 10 "fmt" 11 "os" 12 "path/filepath" 13 "sort" 14 "strings" 15 "syscall" 16 "testing" 17 "time" 18 19 "golang.org/x/sys/windows/svc/mgr" 20 ) 21 22 func TestOpenLanManServer(t *testing.T) { 23 m, err := mgr.Connect() 24 if err != nil { 25 if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED { 26 t.Skip("Skipping test: we don't have rights to manage services.") 27 } 28 t.Fatalf("SCM connection failed: %s", err) 29 } 30 defer m.Disconnect() 31 32 s, err := m.OpenService("LanmanServer") 33 if err != nil { 34 t.Fatalf("OpenService(lanmanserver) failed: %s", err) 35 } 36 defer s.Close() 37 38 _, err = s.Config() 39 if err != nil { 40 t.Fatalf("Config failed: %s", err) 41 } 42 } 43 44 func install(t *testing.T, m *mgr.Mgr, name, exepath string, c mgr.Config) { 45 // Sometimes it takes a while for the service to get 46 // removed after previous test run. 47 for i := 0; ; i++ { 48 s, err := m.OpenService(name) 49 if err != nil { 50 break 51 } 52 s.Close() 53 54 if i > 10 { 55 t.Fatalf("service %s already exists", name) 56 } 57 time.Sleep(300 * time.Millisecond) 58 } 59 60 s, err := m.CreateService(name, exepath, c) 61 if err != nil { 62 t.Fatalf("CreateService(%s) failed: %v", name, err) 63 } 64 defer s.Close() 65 } 66 67 func depString(d []string) string { 68 if len(d) == 0 { 69 return "" 70 } 71 for i := range d { 72 d[i] = strings.ToLower(d[i]) 73 } 74 ss := sort.StringSlice(d) 75 ss.Sort() 76 return strings.Join([]string(ss), " ") 77 } 78 79 func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config { 80 is, err := s.Config() 81 if err != nil { 82 t.Fatalf("Config failed: %s", err) 83 } 84 if should.DelayedAutoStart != is.DelayedAutoStart { 85 t.Fatalf("config mismatch: DelayedAutoStart is %v, but should have %v", is.DelayedAutoStart, should.DelayedAutoStart) 86 } 87 if should.DisplayName != is.DisplayName { 88 t.Fatalf("config mismatch: DisplayName is %q, but should have %q", is.DisplayName, should.DisplayName) 89 } 90 if should.StartType != is.StartType { 91 t.Fatalf("config mismatch: StartType is %v, but should have %v", is.StartType, should.StartType) 92 } 93 if should.Description != is.Description { 94 t.Fatalf("config mismatch: Description is %q, but should have %q", is.Description, should.Description) 95 } 96 if depString(should.Dependencies) != depString(is.Dependencies) { 97 t.Fatalf("config mismatch: Dependencies is %v, but should have %v", is.Dependencies, should.Dependencies) 98 } 99 return is 100 } 101 102 func testRecoveryActions(t *testing.T, s *mgr.Service, should []mgr.RecoveryAction) { 103 is, err := s.RecoveryActions() 104 if err != nil { 105 t.Fatalf("RecoveryActions failed: %s", err) 106 } 107 if len(should) != len(is) { 108 t.Errorf("recovery action mismatch: contains %v actions, but should have %v", len(is), len(should)) 109 } 110 for i, _ := range is { 111 if should[i].Type != is[i].Type { 112 t.Errorf("recovery action mismatch: Type is %v, but should have %v", is[i].Type, should[i].Type) 113 } 114 if should[i].Delay != is[i].Delay { 115 t.Errorf("recovery action mismatch: Delay is %v, but should have %v", is[i].Delay, should[i].Delay) 116 } 117 } 118 } 119 120 func testResetPeriod(t *testing.T, s *mgr.Service, should uint32) { 121 is, err := s.ResetPeriod() 122 if err != nil { 123 t.Fatalf("ResetPeriod failed: %s", err) 124 } 125 if should != is { 126 t.Errorf("reset period mismatch: reset period is %v, but should have %v", is, should) 127 } 128 } 129 130 func testSetRecoveryActions(t *testing.T, s *mgr.Service) { 131 r := []mgr.RecoveryAction{ 132 mgr.RecoveryAction{ 133 Type: mgr.NoAction, 134 Delay: 60000 * time.Millisecond, 135 }, 136 mgr.RecoveryAction{ 137 Type: mgr.ServiceRestart, 138 Delay: 4 * time.Minute, 139 }, 140 mgr.RecoveryAction{ 141 Type: mgr.ServiceRestart, 142 Delay: time.Minute, 143 }, 144 mgr.RecoveryAction{ 145 Type: mgr.RunCommand, 146 Delay: 4000 * time.Millisecond, 147 }, 148 } 149 150 // 4 recovery actions with reset period 151 err := s.SetRecoveryActions(r, uint32(10000)) 152 if err != nil { 153 t.Fatalf("SetRecoveryActions failed: %v", err) 154 } 155 testRecoveryActions(t, s, r) 156 testResetPeriod(t, s, uint32(10000)) 157 158 // Infinite reset period 159 err = s.SetRecoveryActions(r, syscall.INFINITE) 160 if err != nil { 161 t.Fatalf("SetRecoveryActions failed: %v", err) 162 } 163 testRecoveryActions(t, s, r) 164 testResetPeriod(t, s, syscall.INFINITE) 165 166 // nil recovery actions 167 err = s.SetRecoveryActions(nil, 0) 168 if err.Error() != "recoveryActions cannot be nil" { 169 t.Fatalf("SetRecoveryActions failed with unexpected error message of %q", err) 170 } 171 172 // Delete all recovery actions and reset period 173 err = s.ResetRecoveryActions() 174 if err != nil { 175 t.Fatalf("ResetRecoveryActions failed: %v", err) 176 } 177 testRecoveryActions(t, s, nil) 178 testResetPeriod(t, s, 0) 179 } 180 181 func testRebootMessage(t *testing.T, s *mgr.Service, should string) { 182 err := s.SetRebootMessage(should) 183 if err != nil { 184 t.Fatalf("SetRebootMessage failed: %v", err) 185 } 186 is, err := s.RebootMessage() 187 if err != nil { 188 t.Fatalf("RebootMessage failed: %v", err) 189 } 190 if should != is { 191 t.Errorf("reboot message mismatch: message is %q, but should have %q", is, should) 192 } 193 } 194 195 func testRecoveryCommand(t *testing.T, s *mgr.Service, should string) { 196 err := s.SetRecoveryCommand(should) 197 if err != nil { 198 t.Fatalf("SetRecoveryCommand failed: %v", err) 199 } 200 is, err := s.RecoveryCommand() 201 if err != nil { 202 t.Fatalf("RecoveryCommand failed: %v", err) 203 } 204 if should != is { 205 t.Errorf("recovery command mismatch: command is %q, but should have %q", is, should) 206 } 207 } 208 209 func remove(t *testing.T, s *mgr.Service) { 210 err := s.Delete() 211 if err != nil { 212 t.Fatalf("Delete failed: %s", err) 213 } 214 } 215 216 func TestMyService(t *testing.T) { 217 if testing.Short() { 218 t.Skip("skipping test in short mode - it modifies system services") 219 } 220 221 const name = "mymgrservice" 222 223 m, err := mgr.Connect() 224 if err != nil { 225 if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED { 226 t.Skip("Skipping test: we don't have rights to manage services.") 227 } 228 t.Fatalf("SCM connection failed: %s", err) 229 } 230 defer m.Disconnect() 231 232 c := mgr.Config{ 233 StartType: mgr.StartDisabled, 234 DisplayName: "my service", 235 Description: "my service is just a test", 236 Dependencies: []string{"LanmanServer", "W32Time"}, 237 } 238 239 exename := os.Args[0] 240 exepath, err := filepath.Abs(exename) 241 if err != nil { 242 t.Fatalf("filepath.Abs(%s) failed: %s", exename, err) 243 } 244 245 install(t, m, name, exepath, c) 246 247 s, err := m.OpenService(name) 248 if err != nil { 249 t.Fatalf("service %s is not installed", name) 250 } 251 defer s.Close() 252 253 c.BinaryPathName = exepath 254 c = testConfig(t, s, c) 255 256 c.StartType = mgr.StartManual 257 err = s.UpdateConfig(c) 258 if err != nil { 259 t.Fatalf("UpdateConfig failed: %v", err) 260 } 261 262 testConfig(t, s, c) 263 264 c.StartType = mgr.StartAutomatic 265 c.DelayedAutoStart = true 266 err = s.UpdateConfig(c) 267 if err != nil { 268 t.Fatalf("UpdateConfig failed: %v", err) 269 } 270 271 testConfig(t, s, c) 272 273 svcnames, err := m.ListServices() 274 if err != nil { 275 t.Fatalf("ListServices failed: %v", err) 276 } 277 var myserviceIsInstalled bool 278 for _, sn := range svcnames { 279 if sn == name { 280 myserviceIsInstalled = true 281 break 282 } 283 } 284 if !myserviceIsInstalled { 285 t.Errorf("ListServices failed to find %q service", name) 286 } 287 288 testSetRecoveryActions(t, s) 289 testRebootMessage(t, s, fmt.Sprintf("%s failed", name)) 290 testRebootMessage(t, s, "") // delete reboot message 291 testRecoveryCommand(t, s, fmt.Sprintf("sc query %s", name)) 292 testRecoveryCommand(t, s, "") // delete recovery command 293 294 remove(t, s) 295 }