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  }