mirror of
https://github.com/golang/sys.git
synced 2026-02-08 11:46:04 +03:00
ctlHandler is passed to RegisterServiceCtrlHandlerEx as a callback function. But all ctlHandler parameters have to be uintptr aligned regardless of their type. Adjust ctlHandler parameters, so they are aligned accordingly. Also uncomment part of TestExample that verifies passing of ChangeRequest.Context. Fixes golang/go#25660 Change-Id: Ie96fa5c78b911ad9df6775f5c49e7f6d56464f6b Reviewed-on: https://go-review.googlesource.com/c/158698 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
135 lines
3.1 KiB
Go
135 lines
3.1 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build windows
|
|
|
|
package svc_test
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"golang.org/x/sys/windows/svc"
|
|
"golang.org/x/sys/windows/svc/mgr"
|
|
)
|
|
|
|
func getState(t *testing.T, s *mgr.Service) svc.State {
|
|
status, err := s.Query()
|
|
if err != nil {
|
|
t.Fatalf("Query(%s) failed: %s", s.Name, err)
|
|
}
|
|
return status.State
|
|
}
|
|
|
|
func testState(t *testing.T, s *mgr.Service, want svc.State) {
|
|
have := getState(t, s)
|
|
if have != want {
|
|
t.Fatalf("%s state is=%d want=%d", s.Name, have, want)
|
|
}
|
|
}
|
|
|
|
func waitState(t *testing.T, s *mgr.Service, want svc.State) {
|
|
for i := 0; ; i++ {
|
|
have := getState(t, s)
|
|
if have == want {
|
|
return
|
|
}
|
|
if i > 10 {
|
|
t.Fatalf("%s state is=%d, waiting timeout", s.Name, have)
|
|
}
|
|
time.Sleep(300 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func TestExample(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode - it modifies system services")
|
|
}
|
|
|
|
const name = "myservice"
|
|
|
|
m, err := mgr.Connect()
|
|
if err != nil {
|
|
t.Fatalf("SCM connection failed: %s", err)
|
|
}
|
|
defer m.Disconnect()
|
|
|
|
dir, err := ioutil.TempDir("", "svc")
|
|
if err != nil {
|
|
t.Fatalf("failed to create temp directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
exepath := filepath.Join(dir, "a.exe")
|
|
o, err := exec.Command("go", "build", "-o", exepath, "golang.org/x/sys/windows/svc/example").CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("failed to build service program: %v\n%v", err, string(o))
|
|
}
|
|
|
|
s, err := m.OpenService(name)
|
|
if err == nil {
|
|
err = s.Delete()
|
|
if err != nil {
|
|
s.Close()
|
|
t.Fatalf("Delete failed: %s", err)
|
|
}
|
|
s.Close()
|
|
}
|
|
s, err = m.CreateService(name, exepath, mgr.Config{DisplayName: "my service"}, "is", "auto-started")
|
|
if err != nil {
|
|
t.Fatalf("CreateService(%s) failed: %v", name, err)
|
|
}
|
|
defer s.Close()
|
|
|
|
args := []string{"is", "manual-started", fmt.Sprintf("%d", rand.Int())}
|
|
|
|
testState(t, s, svc.Stopped)
|
|
err = s.Start(args...)
|
|
if err != nil {
|
|
t.Fatalf("Start(%s) failed: %s", s.Name, err)
|
|
}
|
|
waitState(t, s, svc.Running)
|
|
time.Sleep(1 * time.Second)
|
|
|
|
// testing deadlock from issues 4.
|
|
_, err = s.Control(svc.Interrogate)
|
|
if err != nil {
|
|
t.Fatalf("Control(%s) failed: %s", s.Name, err)
|
|
}
|
|
_, err = s.Control(svc.Interrogate)
|
|
if err != nil {
|
|
t.Fatalf("Control(%s) failed: %s", s.Name, err)
|
|
}
|
|
time.Sleep(1 * time.Second)
|
|
|
|
_, err = s.Control(svc.Stop)
|
|
if err != nil {
|
|
t.Fatalf("Control(%s) failed: %s", s.Name, err)
|
|
}
|
|
waitState(t, s, svc.Stopped)
|
|
|
|
err = s.Delete()
|
|
if err != nil {
|
|
t.Fatalf("Delete failed: %s", err)
|
|
}
|
|
|
|
out, err := exec.Command("wevtutil.exe", "qe", "Application", "/q:*[System[Provider[@Name='myservice']]]", "/rd:true", "/c:10").CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("wevtutil failed: %v\n%v", err, string(out))
|
|
}
|
|
want := strings.Join(append([]string{name}, args...), "-")
|
|
// Test context passing (see servicemain in sys_386.s and sys_amd64.s).
|
|
want += "-123456"
|
|
if !strings.Contains(string(out), want) {
|
|
t.Errorf("%q string does not contain %q", string(out), want)
|
|
}
|
|
}
|