github.com/HACKERALERT/Picocrypt/src/external/sys@v0.0.0-20210609020157-e519952f829f/windows/svc/svc_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 //go:build windows 6 // +build windows 7 8 package svc_test 9 10 import ( 11 "fmt" 12 "io/ioutil" 13 "math/rand" 14 "os" 15 "os/exec" 16 "path/filepath" 17 "strings" 18 "testing" 19 "time" 20 21 "golang.org/x/sys/windows/svc" 22 "golang.org/x/sys/windows/svc/mgr" 23 ) 24 25 func getState(t *testing.T, s *mgr.Service) svc.State { 26 status, err := s.Query() 27 if err != nil { 28 t.Fatalf("Query(%s) failed: %s", s.Name, err) 29 } 30 return status.State 31 } 32 33 func testState(t *testing.T, s *mgr.Service, want svc.State) { 34 have := getState(t, s) 35 if have != want { 36 t.Fatalf("%s state is=%d want=%d", s.Name, have, want) 37 } 38 } 39 40 func waitState(t *testing.T, s *mgr.Service, want svc.State) { 41 for i := 0; ; i++ { 42 have := getState(t, s) 43 if have == want { 44 return 45 } 46 if i > 10 { 47 t.Fatalf("%s state is=%d, waiting timeout", s.Name, have) 48 } 49 time.Sleep(300 * time.Millisecond) 50 } 51 } 52 53 // stopAndDeleteIfInstalled stops and deletes service name, 54 // if the service is running and / or installed. 55 func stopAndDeleteIfInstalled(t *testing.T, m *mgr.Mgr, name string) { 56 s, err := m.OpenService(name) 57 if err != nil { 58 // Service is not installed. 59 return 60 61 } 62 defer s.Close() 63 64 // Make sure the service is not running, otherwise we won't be able to delete it. 65 if getState(t, s) == svc.Running { 66 _, err = s.Control(svc.Stop) 67 if err != nil { 68 t.Fatalf("Control(%s) failed: %s", s.Name, err) 69 } 70 waitState(t, s, svc.Stopped) 71 } 72 73 err = s.Delete() 74 if err != nil { 75 t.Fatalf("Delete failed: %s", err) 76 } 77 } 78 79 func TestExample(t *testing.T) { 80 if testing.Short() { 81 t.Skip("skipping test in short mode - it modifies system services") 82 } 83 84 const name = "myservice" 85 86 m, err := mgr.Connect() 87 if err != nil { 88 t.Fatalf("SCM connection failed: %s", err) 89 } 90 defer m.Disconnect() 91 92 dir, err := ioutil.TempDir("", "svc") 93 if err != nil { 94 t.Fatalf("failed to create temp directory: %v", err) 95 } 96 defer os.RemoveAll(dir) 97 98 exepath := filepath.Join(dir, "a.exe") 99 o, err := exec.Command("go", "build", "-o", exepath, "golang.org/x/sys/windows/svc/example").CombinedOutput() 100 if err != nil { 101 t.Fatalf("failed to build service program: %v\n%v", err, string(o)) 102 } 103 104 stopAndDeleteIfInstalled(t, m, name) 105 106 s, err := m.CreateService(name, exepath, mgr.Config{DisplayName: "my service"}, "is", "auto-started") 107 if err != nil { 108 t.Fatalf("CreateService(%s) failed: %v", name, err) 109 } 110 defer s.Close() 111 112 args := []string{"is", "manual-started", fmt.Sprintf("%d", rand.Int())} 113 114 testState(t, s, svc.Stopped) 115 err = s.Start(args...) 116 if err != nil { 117 t.Fatalf("Start(%s) failed: %s", s.Name, err) 118 } 119 waitState(t, s, svc.Running) 120 time.Sleep(1 * time.Second) 121 122 // testing deadlock from issues 4. 123 _, err = s.Control(svc.Interrogate) 124 if err != nil { 125 t.Fatalf("Control(%s) failed: %s", s.Name, err) 126 } 127 _, err = s.Control(svc.Interrogate) 128 if err != nil { 129 t.Fatalf("Control(%s) failed: %s", s.Name, err) 130 } 131 time.Sleep(1 * time.Second) 132 133 _, err = s.Control(svc.Stop) 134 if err != nil { 135 t.Fatalf("Control(%s) failed: %s", s.Name, err) 136 } 137 waitState(t, s, svc.Stopped) 138 139 err = s.Delete() 140 if err != nil { 141 t.Fatalf("Delete failed: %s", err) 142 } 143 144 out, err := exec.Command("wevtutil.exe", "qe", "Application", "/q:*[System[Provider[@Name='myservice']]]", "/rd:true", "/c:10").CombinedOutput() 145 if err != nil { 146 t.Fatalf("wevtutil failed: %v\n%v", err, string(out)) 147 } 148 want := strings.Join(append([]string{name}, args...), "-") 149 // Test context passing (see servicemain in sys_386.s and sys_amd64.s). 150 want += "-123456" 151 if !strings.Contains(string(out), want) { 152 t.Errorf("%q string does not contain %q", string(out), want) 153 } 154 } 155 156 func TestIsAnInteractiveSession(t *testing.T) { 157 isInteractive, err := svc.IsAnInteractiveSession() 158 if err != nil { 159 t.Fatal(err) 160 } 161 if !isInteractive { 162 t.Error("IsAnInteractiveSession retuns false when running interactively.") 163 } 164 } 165 166 func TestIsWindowsService(t *testing.T) { 167 isSvc, err := svc.IsWindowsService() 168 if err != nil { 169 t.Fatal(err) 170 } 171 if isSvc { 172 t.Error("IsWindowsService retuns true when not running in a service.") 173 } 174 } 175 176 func TestIsWindowsServiceWhenParentExits(t *testing.T) { 177 if os.Getenv("GO_WANT_HELPER_PROCESS") == "parent" { 178 // in parent process 179 180 // Start the child and exit quickly. 181 child := exec.Command(os.Args[0], "-test.run=TestIsWindowsServiceWhenParentExits") 182 child.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=child") 183 err := child.Start() 184 if err != nil { 185 fmt.Fprintf(os.Stderr, fmt.Sprintf("child start failed: %v", err)) 186 os.Exit(1) 187 } 188 os.Exit(0) 189 } 190 191 if os.Getenv("GO_WANT_HELPER_PROCESS") == "child" { 192 // in child process 193 dumpPath := os.Getenv("GO_WANT_HELPER_PROCESS_FILE") 194 if dumpPath == "" { 195 // We cannot report this error. But main test will notice 196 // that we did not create dump file. 197 os.Exit(1) 198 } 199 var msg string 200 isSvc, err := svc.IsWindowsService() 201 if err != nil { 202 msg = err.Error() 203 } 204 if isSvc { 205 msg = "IsWindowsService retuns true when not running in a service." 206 } 207 err = ioutil.WriteFile(dumpPath, []byte(msg), 0644) 208 if err != nil { 209 // We cannot report this error. But main test will notice 210 // that we did not create dump file. 211 os.Exit(2) 212 } 213 os.Exit(0) 214 } 215 216 // Run in a loop until it fails. 217 for i := 0; i < 10; i++ { 218 childDumpPath := filepath.Join(t.TempDir(), "issvc.txt") 219 220 parent := exec.Command(os.Args[0], "-test.run=TestIsWindowsServiceWhenParentExits") 221 parent.Env = append(os.Environ(), 222 "GO_WANT_HELPER_PROCESS=parent", 223 "GO_WANT_HELPER_PROCESS_FILE="+childDumpPath) 224 parentOutput, err := parent.CombinedOutput() 225 if err != nil { 226 t.Errorf("parent failed: %v: %v", err, string(parentOutput)) 227 } 228 for i := 0; ; i++ { 229 if _, err := os.Stat(childDumpPath); err == nil { 230 break 231 } 232 time.Sleep(100 * time.Millisecond) 233 if i > 10 { 234 t.Fatal("timed out waiting for child ouput file to be created.") 235 } 236 } 237 childOutput, err := ioutil.ReadFile(childDumpPath) 238 if err != nil { 239 t.Fatalf("reading child ouput failed: %v", err) 240 } 241 if got, want := string(childOutput), ""; got != want { 242 t.Fatalf("child output: want %q, got %q", want, got) 243 } 244 } 245 }