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