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