1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package bpm
17
18 import (
19 "context"
20 "math/rand"
21 "time"
22
23 . "github.com/onsi/ginkgo"
24 . "github.com/onsi/gomega"
25 "github.com/shirou/gopsutil/process"
26 )
27
28 func RandomeIdentifier() string {
29 var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
30
31 s := make([]rune, 10)
32 for i := range s {
33 s[i] = letters[rand.Intn(len(letters))]
34 }
35 return string(s)
36 }
37
38 func WaitProcess(m *BackgroundProcessManager, cmd *ManagedProcess, exceedTime time.Duration) {
39 pid := cmd.Process.Pid
40 procState, err := process.NewProcess(int32(pid))
41 Expect(err).To(BeNil())
42 ct, err := procState.CreateTime()
43 Expect(err).To(BeNil())
44 pair := ProcessPair{
45 Pid: pid,
46 CreateTime: ct,
47 }
48 channel, ok := m.deathSig.Load(pair)
49 Expect(ok).To(BeTrue())
50 deathChannel := channel.(chan bool)
51
52 timeExceed := false
53 select {
54 case <-deathChannel:
55 case <-time.Tick(exceedTime):
56 timeExceed = true
57 }
58 Expect(timeExceed).To(BeFalse())
59 }
60
61 var _ = Describe("background process manager", func() {
62 m := NewBackgroundProcessManager()
63
64 Context("normally exited process", func() {
65 It("should work", func() {
66 cmd := DefaultProcessBuilder("sleep", "2").Build()
67 _, err := m.StartProcess(cmd)
68 Expect(err).To(BeNil())
69
70 WaitProcess(&m, cmd, time.Second*5)
71 })
72
73 It("processes with the same identifier", func() {
74 identifier := RandomeIdentifier()
75
76 cmd := DefaultProcessBuilder("sleep", "2").
77 SetIdentifier(identifier).
78 Build()
79 _, err := m.StartProcess(cmd)
80 Expect(err).To(BeNil())
81
82 startTime := time.Now()
83 cmd2 := DefaultProcessBuilder("sleep", "2").
84 SetIdentifier(identifier).
85 Build()
86 _, err = m.StartProcess(cmd2)
87 costedTime := time.Since(startTime)
88 Expect(err).To(BeNil())
89 Expect(costedTime.Seconds()).Should(BeNumerically(">", 1.9))
90
91 _, err = process.NewProcess(int32(cmd.Process.Pid))
92 Expect(err).NotTo(BeNil())
93
94 WaitProcess(&m, cmd2, time.Second*5)
95 })
96 })
97
98 Context("kill process", func() {
99 It("should work", func() {
100 cmd := DefaultProcessBuilder("sleep", "2").Build()
101 _, err := m.StartProcess(cmd)
102 Expect(err).To(BeNil())
103
104 pid := cmd.Process.Pid
105 procState, err := process.NewProcess(int32(pid))
106 Expect(err).To(BeNil())
107 ct, err := procState.CreateTime()
108 Expect(err).To(BeNil())
109
110 err = m.KillBackgroundProcess(context.Background(), pid, ct)
111 Expect(err).To(BeNil())
112
113 _, err = process.NewProcess(int32(pid))
114 Expect(err).NotTo(BeNil())
115 })
116
117 It("process with the same identifier", func() {
118 identifier := RandomeIdentifier()
119
120 cmd := DefaultProcessBuilder("sleep", "2").
121 SetIdentifier(identifier).
122 Build()
123 _, err := m.StartProcess(cmd)
124 Expect(err).To(BeNil())
125
126 pid := cmd.Process.Pid
127 procState, err := process.NewProcess(int32(pid))
128 Expect(err).To(BeNil())
129 ct, err := procState.CreateTime()
130 Expect(err).To(BeNil())
131
132 cmd2 := DefaultProcessBuilder("sleep", "2").
133 SetIdentifier(identifier).
134 Build()
135
136 go func() {
137 time.Sleep(time.Second)
138
139 err = m.KillBackgroundProcess(context.Background(), pid, ct)
140 Expect(err).To(BeNil())
141 }()
142
143 startTime := time.Now()
144 _, err = m.StartProcess(cmd2)
145 costedTime := time.Since(startTime)
146 Expect(err).To(BeNil())
147 Expect(costedTime.Seconds()).Should(And(BeNumerically("<", 2), BeNumerically(">", 1)))
148
149 pid2 := cmd2.Process.Pid
150 procState2, err := process.NewProcess(int32(pid2))
151 Expect(err).To(BeNil())
152 ct2, err := procState2.CreateTime()
153 Expect(err).To(BeNil())
154
155 err = m.KillBackgroundProcess(context.Background(), pid2, ct2)
156 Expect(err).To(BeNil())
157 })
158 })
159 })
160