github.com/as/shiny@v0.8.2/sys/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  	"os"
    11  	"path/filepath"
    12  	"sort"
    13  	"strings"
    14  	"syscall"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/as/shiny/sys/windows/svc/mgr"
    19  )
    20  
    21  func TestOpenLanManServer(t *testing.T) {
    22  	m, err := mgr.Connect()
    23  	if err != nil {
    24  		if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED {
    25  			t.Skip("Skipping test: we don't have rights to manage services.")
    26  		}
    27  		t.Fatalf("SCM connection failed: %s", err)
    28  	}
    29  	defer m.Disconnect()
    30  
    31  	s, err := m.OpenService("LanmanServer")
    32  	if err != nil {
    33  		t.Fatalf("OpenService(lanmanserver) failed: %s", err)
    34  	}
    35  	defer s.Close()
    36  
    37  	_, err = s.Config()
    38  	if err != nil {
    39  		t.Fatalf("Config failed: %s", err)
    40  	}
    41  }
    42  
    43  func install(t *testing.T, m *mgr.Mgr, name, exepath string, c mgr.Config) {
    44  	// Sometimes it takes a while for the service to get
    45  	// removed after previous test run.
    46  	for i := 0; ; i++ {
    47  		s, err := m.OpenService(name)
    48  		if err != nil {
    49  			break
    50  		}
    51  		s.Close()
    52  
    53  		if i > 10 {
    54  			t.Fatalf("service %s already exists", name)
    55  		}
    56  		time.Sleep(300 * time.Millisecond)
    57  	}
    58  
    59  	s, err := m.CreateService(name, exepath, c)
    60  	if err != nil {
    61  		t.Fatalf("CreateService(%s) failed: %v", name, err)
    62  	}
    63  	defer s.Close()
    64  }
    65  
    66  func depString(d []string) string {
    67  	if len(d) == 0 {
    68  		return ""
    69  	}
    70  	for i := range d {
    71  		d[i] = strings.ToLower(d[i])
    72  	}
    73  	ss := sort.StringSlice(d)
    74  	ss.Sort()
    75  	return strings.Join([]string(ss), " ")
    76  }
    77  
    78  func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config {
    79  	is, err := s.Config()
    80  	if err != nil {
    81  		t.Fatalf("Config failed: %s", err)
    82  	}
    83  	if should.DisplayName != is.DisplayName {
    84  		t.Fatalf("config mismatch: DisplayName is %q, but should have %q", is.DisplayName, should.DisplayName)
    85  	}
    86  	if should.StartType != is.StartType {
    87  		t.Fatalf("config mismatch: StartType is %v, but should have %v", is.StartType, should.StartType)
    88  	}
    89  	if should.Description != is.Description {
    90  		t.Fatalf("config mismatch: Description is %q, but should have %q", is.Description, should.Description)
    91  	}
    92  	if depString(should.Dependencies) != depString(is.Dependencies) {
    93  		t.Fatalf("config mismatch: Dependencies is %v, but should have %v", is.Dependencies, should.Dependencies)
    94  	}
    95  	return is
    96  }
    97  
    98  func remove(t *testing.T, s *mgr.Service) {
    99  	err := s.Delete()
   100  	if err != nil {
   101  		t.Fatalf("Delete failed: %s", err)
   102  	}
   103  }
   104  
   105  func TestMyService(t *testing.T) {
   106  	if testing.Short() {
   107  		t.Skip("skipping test in short mode - it modifies system services")
   108  	}
   109  
   110  	const name = "myservice"
   111  
   112  	m, err := mgr.Connect()
   113  	if err != nil {
   114  		if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED {
   115  			t.Skip("Skipping test: we don't have rights to manage services.")
   116  		}
   117  		t.Fatalf("SCM connection failed: %s", err)
   118  	}
   119  	defer m.Disconnect()
   120  
   121  	c := mgr.Config{
   122  		StartType:    mgr.StartDisabled,
   123  		DisplayName:  "my service",
   124  		Description:  "my service is just a test",
   125  		Dependencies: []string{"LanmanServer", "W32Time"},
   126  	}
   127  
   128  	exename := os.Args[0]
   129  	exepath, err := filepath.Abs(exename)
   130  	if err != nil {
   131  		t.Fatalf("filepath.Abs(%s) failed: %s", exename, err)
   132  	}
   133  
   134  	install(t, m, name, exepath, c)
   135  
   136  	s, err := m.OpenService(name)
   137  	if err != nil {
   138  		t.Fatalf("service %s is not installed", name)
   139  	}
   140  	defer s.Close()
   141  
   142  	c.BinaryPathName = exepath
   143  	c = testConfig(t, s, c)
   144  
   145  	c.StartType = mgr.StartManual
   146  	err = s.UpdateConfig(c)
   147  	if err != nil {
   148  		t.Fatalf("UpdateConfig failed: %v", err)
   149  	}
   150  
   151  	testConfig(t, s, c)
   152  
   153  	svcnames, err := m.ListServices()
   154  	if err != nil {
   155  		t.Fatalf("ListServices failed: %v", err)
   156  	}
   157  	var myserviceIsInstalled bool
   158  	for _, sn := range svcnames {
   159  		if sn == name {
   160  			myserviceIsInstalled = true
   161  			break
   162  		}
   163  	}
   164  	if !myserviceIsInstalled {
   165  		t.Errorf("ListServices failed to find %q service", name)
   166  	}
   167  
   168  	remove(t, s)
   169  }