~ubuntu-branches/ubuntu/vivid/juju-core/vivid-updates

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/service/upstart/upstart_test.go

  • Committer: Package Import Robot
  • Author(s): Curtis C. Hovey
  • Date: 2015-09-29 19:43:29 UTC
  • mfrom: (47.1.4 wily-proposed)
  • Revision ID: package-import@ubuntu.com-20150929194329-9y496tbic30hc7vp
Tags: 1.24.6-0ubuntu1~15.04.1
Backport of 1.24.6 from wily. (LP: #1500916, #1497087)

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
        "io/ioutil"
9
9
        "os"
10
10
        "path/filepath"
 
11
        "runtime"
11
12
        "testing"
12
13
 
13
14
        jc "github.com/juju/testing/checkers"
20
21
        coretesting "github.com/juju/juju/testing"
21
22
)
22
23
 
23
 
func Test(t *testing.T) { gc.TestingT(t) }
 
24
func Test(t *testing.T) {
 
25
        if runtime.GOOS == "windows" {
 
26
                t.Skip("Skipping upstart tests on windows")
 
27
        }
 
28
        gc.TestingT(t)
 
29
}
24
30
 
25
31
type UpstartSuite struct {
26
32
        coretesting.BaseSuite
35
41
        s.testPath = c.MkDir()
36
42
        s.initDir = c.MkDir()
37
43
        s.PatchEnvPathPrepend(s.testPath)
38
 
        s.PatchValue(&upstart.InstallStartRetryAttempts, utils.AttemptStrategy{})
39
44
        s.PatchValue(&upstart.InitDir, s.initDir)
40
45
        s.service = upstart.NewService(
41
46
                "some-service",
42
47
                common.Conf{
43
 
                        Desc: "some service",
44
 
                        Cmd:  "some command",
 
48
                        Desc:      "some service",
 
49
                        ExecStart: "/path/to/some-command",
45
50
                },
46
51
        )
47
52
}
69
74
        s.MakeTool(c, "status", `echo "some-service stop/waiting"`)
70
75
}
71
76
 
72
 
func (s *UpstartSuite) RunningStatus(c *gc.C) {
 
77
func (s *UpstartSuite) RunningStatusNoProcessID(c *gc.C) {
 
78
        s.MakeTool(c, "status", `echo "some-service start/running"`)
 
79
}
 
80
 
 
81
func (s *UpstartSuite) RunningStatusWithProcessID(c *gc.C) {
73
82
        s.MakeTool(c, "status", `echo "some-service start/running, process 123"`)
74
83
}
75
84
 
76
 
func (s *UpstartSuite) TestInitDir(c *gc.C) {
77
 
        svc := upstart.NewService("blah", common.Conf{})
78
 
        c.Assert(svc.Conf.InitDir, gc.Equals, s.initDir)
79
 
}
80
 
 
81
85
func (s *UpstartSuite) goodInstall(c *gc.C) {
82
86
        s.MakeTool(c, "start", "exit 0")
83
87
        err := s.service.Install()
85
89
}
86
90
 
87
91
func (s *UpstartSuite) TestInstalled(c *gc.C) {
88
 
        c.Assert(s.service.Installed(), jc.IsFalse)
 
92
        installed, err := s.service.Installed()
 
93
        c.Assert(err, jc.ErrorIsNil)
 
94
        c.Check(installed, jc.IsFalse)
 
95
 
89
96
        s.goodInstall(c)
90
 
        c.Assert(s.service.Installed(), jc.IsTrue)
 
97
        installed, err = s.service.Installed()
 
98
        c.Assert(err, jc.ErrorIsNil)
 
99
        c.Check(installed, jc.IsTrue)
91
100
}
92
101
 
93
102
func (s *UpstartSuite) TestExists(c *gc.C) {
94
103
        // Setup creates the file, but it is empty.
95
 
        c.Assert(s.service.Exists(), jc.IsFalse)
 
104
        exists, err := s.service.Exists()
 
105
        c.Assert(err, jc.ErrorIsNil)
 
106
        c.Check(exists, jc.IsFalse)
 
107
 
96
108
        s.goodInstall(c)
97
 
        c.Assert(s.service.Exists(), jc.IsTrue)
 
109
        exists, err = s.service.Exists()
 
110
        c.Assert(err, jc.ErrorIsNil)
 
111
        c.Check(exists, jc.IsTrue)
98
112
}
99
113
 
100
114
func (s *UpstartSuite) TestExistsNonEmpty(c *gc.C) {
101
115
        s.goodInstall(c)
102
 
        s.service.Conf.Cmd = "something else"
103
 
        c.Assert(s.service.Exists(), jc.IsFalse)
 
116
        s.service.Service.Conf.ExecStart = "/path/to/other-command"
 
117
 
 
118
        exists, err := s.service.Exists()
 
119
        c.Assert(err, jc.ErrorIsNil)
 
120
        c.Check(exists, jc.IsFalse)
104
121
}
105
122
 
106
123
func (s *UpstartSuite) TestRunning(c *gc.C) {
107
124
        s.MakeTool(c, "status", "exit 1")
108
 
        c.Assert(s.service.Running(), jc.IsFalse)
 
125
        running, err := s.service.Running()
 
126
        c.Assert(err, jc.ErrorIsNil)
 
127
        c.Check(running, jc.IsFalse)
 
128
 
109
129
        s.MakeTool(c, "status", `echo "GIBBERISH NONSENSE"`)
110
 
        c.Assert(s.service.Running(), jc.IsFalse)
111
 
        s.RunningStatus(c)
112
 
        c.Assert(s.service.Running(), jc.IsTrue)
 
130
        running, err = s.service.Running()
 
131
        c.Assert(err, jc.ErrorIsNil)
 
132
        c.Check(running, jc.IsFalse)
 
133
 
 
134
        s.RunningStatusNoProcessID(c)
 
135
        running, err = s.service.Running()
 
136
        c.Assert(err, jc.ErrorIsNil)
 
137
        c.Check(running, jc.IsTrue)
 
138
 
 
139
        s.RunningStatusWithProcessID(c)
 
140
        running, err = s.service.Running()
 
141
        c.Assert(err, jc.ErrorIsNil)
 
142
        c.Check(running, jc.IsTrue)
113
143
}
114
144
 
115
145
func (s *UpstartSuite) TestStart(c *gc.C) {
116
 
        s.RunningStatus(c)
 
146
        s.RunningStatusWithProcessID(c)
117
147
        s.MakeTool(c, "start", "exit 99")
118
 
        c.Assert(s.service.Start(), gc.IsNil)
 
148
        c.Assert(s.service.Start(), jc.ErrorIsNil)
119
149
        s.StoppedStatus(c)
120
150
        c.Assert(s.service.Start(), gc.ErrorMatches, ".*exit status 99.*")
121
151
        s.MakeTool(c, "start", "exit 0")
122
 
        c.Assert(s.service.Start(), gc.IsNil)
 
152
        c.Assert(s.service.Start(), jc.ErrorIsNil)
123
153
}
124
154
 
125
155
func (s *UpstartSuite) TestStop(c *gc.C) {
126
156
        s.StoppedStatus(c)
127
157
        s.MakeTool(c, "stop", "exit 99")
128
 
        c.Assert(s.service.Stop(), gc.IsNil)
129
 
        s.RunningStatus(c)
 
158
        c.Assert(s.service.Stop(), jc.ErrorIsNil)
 
159
        s.RunningStatusWithProcessID(c)
130
160
        c.Assert(s.service.Stop(), gc.ErrorMatches, ".*exit status 99.*")
131
161
        s.MakeTool(c, "stop", "exit 0")
132
 
        c.Assert(s.service.Stop(), gc.IsNil)
 
162
        c.Assert(s.service.Stop(), jc.ErrorIsNil)
133
163
}
134
164
 
135
165
func (s *UpstartSuite) TestRemoveMissing(c *gc.C) {
136
 
        c.Assert(s.service.StopAndRemove(), gc.IsNil)
 
166
        err := s.service.Remove()
 
167
 
 
168
        c.Check(err, jc.ErrorIsNil)
137
169
}
138
170
 
139
171
func (s *UpstartSuite) TestRemoveStopped(c *gc.C) {
140
172
        s.goodInstall(c)
141
173
        s.StoppedStatus(c)
142
 
        c.Assert(s.service.StopAndRemove(), gc.IsNil)
143
 
        _, err := os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf"))
144
 
        c.Assert(err, jc.Satisfies, os.IsNotExist)
 
174
 
 
175
        err := s.service.Remove()
 
176
        c.Assert(err, jc.ErrorIsNil)
 
177
 
 
178
        filename := filepath.Join(upstart.InitDir, "some-service.conf")
 
179
        _, err = os.Stat(filename)
 
180
        c.Check(err, jc.Satisfies, os.IsNotExist)
145
181
}
146
182
 
147
 
func (s *UpstartSuite) TestRemoveRunning(c *gc.C) {
 
183
func (s *UpstartSuite) TestStopRunning(c *gc.C) {
148
184
        s.goodInstall(c)
149
 
        s.RunningStatus(c)
 
185
        s.RunningStatusWithProcessID(c)
150
186
        s.MakeTool(c, "stop", "exit 99")
151
 
        c.Assert(s.service.StopAndRemove(), gc.ErrorMatches, ".*exit status 99.*")
152
 
        _, err := os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf"))
 
187
        filename := filepath.Join(upstart.InitDir, "some-service.conf")
 
188
        err := s.service.Stop()
 
189
        c.Assert(err, gc.ErrorMatches, ".*exit status 99.*")
 
190
 
 
191
        _, err = os.Stat(filename)
153
192
        c.Assert(err, jc.ErrorIsNil)
 
193
 
154
194
        s.MakeTool(c, "stop", "exit 0")
155
 
        c.Assert(s.service.StopAndRemove(), gc.IsNil)
156
 
        _, err = os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf"))
157
 
        c.Assert(err, jc.Satisfies, os.IsNotExist)
158
 
}
159
 
 
160
 
func (s *UpstartSuite) TestStopAndRemove(c *gc.C) {
161
 
        s.goodInstall(c)
162
 
        s.RunningStatus(c)
163
 
        s.MakeTool(c, "stop", "exit 99")
164
 
 
165
 
        // StopAndRemove will fail, as it calls stop.
166
 
        c.Assert(s.service.StopAndRemove(), gc.ErrorMatches, ".*exit status 99.*")
167
 
        _, err := os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf"))
 
195
        err = s.service.Stop()
168
196
        c.Assert(err, jc.ErrorIsNil)
169
 
 
170
 
        // Plain old Remove will succeed.
171
 
        c.Assert(s.service.Remove(), gc.IsNil)
172
 
        _, err = os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf"))
173
 
        c.Assert(err, jc.Satisfies, os.IsNotExist)
174
197
}
175
198
 
176
199
func (s *UpstartSuite) TestInstallErrors(c *gc.C) {
180
203
                _, err := s.service.InstallCommands()
181
204
                c.Assert(err, gc.ErrorMatches, msg)
182
205
        }
183
 
        s.service.Conf = conf
184
 
        s.service.Name = ""
 
206
        s.service.Service.Conf = conf
 
207
        s.service.Service.Name = ""
185
208
        check("missing Name")
186
 
        s.service.Name = "some-service"
187
 
        check("missing InitDir")
188
 
        s.service.Conf.InitDir = c.MkDir()
 
209
        s.service.Service.Name = "some-service"
189
210
        check("missing Desc")
190
 
        s.service.Conf.Desc = "this is an upstart service"
191
 
        check("missing Cmd")
 
211
        s.service.Service.Conf.Desc = "this is an upstart service"
 
212
        check("missing ExecStart")
192
213
}
193
214
 
194
215
const expectStart = `description "this is an upstart service"
201
222
 
202
223
func (s *UpstartSuite) dummyConf(c *gc.C) common.Conf {
203
224
        return common.Conf{
204
 
                Desc:    "this is an upstart service",
205
 
                Cmd:     "do something",
206
 
                InitDir: s.initDir,
 
225
                Desc:      "this is an upstart service",
 
226
                ExecStart: "/path/to/some-command x y z",
207
227
        }
208
228
}
209
229
 
210
230
func (s *UpstartSuite) assertInstall(c *gc.C, conf common.Conf, expectEnd string) {
211
231
        expectContent := expectStart + expectEnd
212
 
        expectPath := filepath.Join(conf.InitDir, "some-service.conf")
 
232
        expectPath := filepath.Join(upstart.InitDir, "some-service.conf")
213
233
 
214
 
        s.service.Conf = conf
 
234
        s.service.Service.Conf = conf
215
235
        svc := s.service
216
236
        cmds, err := s.service.InstallCommands()
217
237
        c.Assert(err, jc.ErrorIsNil)
218
238
        c.Assert(cmds, gc.DeepEquals, []string{
219
 
                "cat >> " + expectPath + " << 'EOF'\n" + expectContent + "EOF\n",
 
239
                "cat > " + expectPath + " << 'EOF'\n" + expectContent + "EOF\n",
 
240
        })
 
241
        cmds, err = s.service.StartCommands()
 
242
        c.Assert(err, jc.ErrorIsNil)
 
243
        c.Assert(cmds, gc.DeepEquals, []string{
220
244
                "start some-service",
221
245
        })
222
246
 
 
247
        s.MakeTool(c, "status", `echo "some-service stop/waiting"`)
223
248
        s.MakeTool(c, "start", "exit 99")
224
249
        err = svc.Install()
 
250
        c.Assert(err, jc.ErrorIsNil)
 
251
        err = svc.Start()
225
252
        c.Assert(err, gc.ErrorMatches, ".*exit status 99.*")
 
253
 
226
254
        s.MakeTool(c, "start", "exit 0")
227
255
        err = svc.Install()
228
256
        c.Assert(err, jc.ErrorIsNil)
 
257
        err = svc.Start()
 
258
        c.Assert(err, jc.ErrorIsNil)
 
259
 
229
260
        content, err := ioutil.ReadFile(expectPath)
230
261
        c.Assert(err, jc.ErrorIsNil)
231
262
        c.Assert(string(content), gc.Equals, expectContent)
233
264
 
234
265
func (s *UpstartSuite) TestInstallSimple(c *gc.C) {
235
266
        conf := s.dummyConf(c)
236
 
        s.assertInstall(c, conf, "\n\nscript\n\n\n  exec do something\nend script\n")
 
267
        s.assertInstall(c, conf, `
 
268
 
 
269
script
 
270
 
 
271
 
 
272
  exec /path/to/some-command x y z
 
273
end script
 
274
`)
237
275
}
238
276
 
239
277
func (s *UpstartSuite) TestInstallExtraScript(c *gc.C) {
240
278
        conf := s.dummyConf(c)
241
279
        conf.ExtraScript = "extra lines of script"
242
 
        s.assertInstall(c, conf, "\n\nscript\nextra lines of script\n\n  exec do something\nend script\n")
 
280
        s.assertInstall(c, conf, `
 
281
 
 
282
script
 
283
extra lines of script
 
284
 
 
285
  exec /path/to/some-command x y z
 
286
end script
 
287
`)
243
288
}
244
289
 
245
 
func (s *UpstartSuite) TestInstallOutput(c *gc.C) {
 
290
func (s *UpstartSuite) TestInstallLogfile(c *gc.C) {
246
291
        conf := s.dummyConf(c)
247
 
        conf.Out = "/some/output/path"
248
 
        s.assertInstall(c, conf, "\n\nscript\n\n\n  # Ensure log files are properly protected\n  touch /some/output/path\n  chown syslog:syslog /some/output/path\n  chmod 0600 /some/output/path\n\n  exec do something >> /some/output/path 2>&1\nend script\n")
 
292
        conf.Logfile = "/some/output/path"
 
293
        s.assertInstall(c, conf, `
 
294
 
 
295
script
 
296
 
 
297
 
 
298
  # Ensure log files are properly protected
 
299
  touch /some/output/path
 
300
  chown syslog:syslog /some/output/path
 
301
  chmod 0600 /some/output/path
 
302
 
 
303
  exec /path/to/some-command x y z >> /some/output/path 2>&1
 
304
end script
 
305
`)
249
306
}
250
307
 
251
308
func (s *UpstartSuite) TestInstallEnv(c *gc.C) {
258
315
script
259
316
 
260
317
 
261
 
  exec do something
 
318
  exec /path/to/some-command x y z
262
319
end script
263
320
`)
264
321
}
265
322
 
266
323
func (s *UpstartSuite) TestInstallLimit(c *gc.C) {
267
324
        conf := s.dummyConf(c)
268
 
        conf.Limit = map[string]string{"nofile": "65000 65000", "nproc": "20000 20000"}
 
325
        conf.Limit = map[string]int{
 
326
                "nofile": 65000,
 
327
                "nproc":  20000,
 
328
        }
269
329
        s.assertInstall(c, conf, `
270
330
limit nofile 65000 65000
271
331
limit nproc 20000 20000
273
333
script
274
334
 
275
335
 
276
 
  exec do something
 
336
  exec /path/to/some-command x y z
277
337
end script
278
338
`)
279
339
}
295
355
        err := symlink.New(pathTo("status-started"), pathTo("status"))
296
356
        c.Assert(err, jc.ErrorIsNil)
297
357
 
298
 
        conf := s.dummyConf(c)
299
 
        s.service.UpdateConfig(conf)
300
 
        err = s.service.Install()
301
 
        c.Assert(err, jc.ErrorIsNil)
302
 
        c.Assert(s.service, jc.Satisfies, (*upstart.Service).Running)
 
358
        svc := upstart.NewService("some-service", s.dummyConf(c))
 
359
        err = svc.Install()
 
360
        c.Assert(err, jc.ErrorIsNil)
 
361
        installed, err := svc.Running()
 
362
        c.Assert(err, jc.ErrorIsNil)
 
363
        c.Check(installed, jc.IsTrue)
 
364
}
 
365
 
 
366
type IsRunningSuite struct {
 
367
        coretesting.BaseSuite
 
368
}
 
369
 
 
370
var _ = gc.Suite(&IsRunningSuite{})
 
371
 
 
372
const modeExecutable = 0500
 
373
const modeNotExecutable = 0400
 
374
 
 
375
// createInitctl creates a dummy initctl which returns the given
 
376
// exitcode and patches the upstart package to use it.
 
377
func (s *IsRunningSuite) createInitctl(c *gc.C, stderr string, exitcode int, mode os.FileMode) {
 
378
        path := filepath.Join(c.MkDir(), "initctl")
 
379
        var body string
 
380
        if stderr != "" {
 
381
                // Write to stderr.
 
382
                body = ">&2 echo " + utils.ShQuote(stderr)
 
383
        }
 
384
        script := fmt.Sprintf(`
 
385
#!/usr/bin/env bash
 
386
%s
 
387
exit %d
 
388
`[1:], body, exitcode)
 
389
        c.Logf(script)
 
390
        err := ioutil.WriteFile(path, []byte(script), mode)
 
391
        c.Assert(err, jc.ErrorIsNil)
 
392
        s.PatchValue(upstart.InitctlPath, path)
 
393
}
 
394
 
 
395
func (s *IsRunningSuite) TestUpstartInstalled(c *gc.C) {
 
396
        s.createInitctl(c, "", 0, modeExecutable)
 
397
 
 
398
        isUpstart, err := upstart.IsRunning()
 
399
        c.Assert(isUpstart, jc.IsTrue)
 
400
        c.Assert(err, jc.ErrorIsNil)
 
401
}
 
402
 
 
403
func (s *IsRunningSuite) TestUpstartNotInstalled(c *gc.C) {
 
404
        s.PatchValue(upstart.InitctlPath, "/foo/bar/not-exist")
 
405
 
 
406
        isUpstart, err := upstart.IsRunning()
 
407
        c.Assert(isUpstart, jc.IsFalse)
 
408
        c.Assert(err, jc.ErrorIsNil)
 
409
}
 
410
 
 
411
func (s *IsRunningSuite) TestUpstartInstalledButBroken(c *gc.C) {
 
412
        const stderr = "<something broke>"
 
413
        const errorCode = 99
 
414
        s.createInitctl(c, stderr, errorCode, modeExecutable)
 
415
 
 
416
        isUpstart, err := upstart.IsRunning()
 
417
        c.Assert(isUpstart, jc.IsFalse)
 
418
        c.Assert(err, gc.ErrorMatches, fmt.Sprintf(".*exit status %d", errorCode))
 
419
}
 
420
 
 
421
func (s *IsRunningSuite) TestUpstartInstalledButNotRunning(c *gc.C) {
 
422
        const stderr = `Name "com.ubuntu.Upstart" does not exist`
 
423
        const errorCode = 1
 
424
        s.createInitctl(c, stderr, errorCode, modeExecutable)
 
425
 
 
426
        isUpstart, err := upstart.IsRunning()
 
427
        c.Assert(isUpstart, jc.IsFalse)
 
428
        c.Assert(err, gc.ErrorMatches, fmt.Sprintf(".*exit status %d", errorCode))
 
429
}
 
430
 
 
431
func (s *IsRunningSuite) TestInitctlCantBeRun(c *gc.C) {
 
432
        s.createInitctl(c, "", 0, modeNotExecutable)
 
433
 
 
434
        isUpstart, err := upstart.IsRunning()
 
435
        c.Assert(isUpstart, jc.IsFalse)
 
436
        c.Assert(err, gc.ErrorMatches, ".+: permission denied")
303
437
}