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

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/worker/uniter/storage/state_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:
 
1
// Copyright 2015 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package storage_test
 
5
 
 
6
import (
 
7
        "io/ioutil"
 
8
        "os"
 
9
        "path/filepath"
 
10
 
 
11
        "github.com/juju/errors"
 
12
        "github.com/juju/names"
 
13
        jc "github.com/juju/testing/checkers"
 
14
        gc "gopkg.in/check.v1"
 
15
        "gopkg.in/juju/charm.v5/hooks"
 
16
 
 
17
        "github.com/juju/juju/testing"
 
18
        "github.com/juju/juju/worker/uniter/hook"
 
19
        "github.com/juju/juju/worker/uniter/storage"
 
20
)
 
21
 
 
22
type stateSuite struct {
 
23
        testing.BaseSuite
 
24
}
 
25
 
 
26
var _ = gc.Suite(&stateSuite{})
 
27
 
 
28
func writeFile(c *gc.C, path string, content string) {
 
29
        err := ioutil.WriteFile(path, []byte(content), 0644)
 
30
        c.Assert(err, jc.ErrorIsNil)
 
31
}
 
32
 
 
33
func assertFileNotExist(c *gc.C, path string) {
 
34
        _, err := os.Stat(path)
 
35
        c.Assert(err, jc.Satisfies, os.IsNotExist)
 
36
}
 
37
 
 
38
func (s *stateSuite) TestReadAllStateFiles(c *gc.C) {
 
39
        dir := c.MkDir()
 
40
        writeFile(c, filepath.Join(dir, "data-0"), "attached: true")
 
41
        // We don't currently ever write a file with attached=false,
 
42
        // but test it for coverage in case of required changes.
 
43
        writeFile(c, filepath.Join(dir, "data-1"), "attached: false")
 
44
 
 
45
        states, err := storage.ReadAllStateFiles(dir)
 
46
        c.Assert(err, jc.ErrorIsNil)
 
47
        c.Assert(states, gc.HasLen, 2)
 
48
 
 
49
        state, ok := states[names.NewStorageTag("data/0")]
 
50
        c.Assert(ok, jc.IsTrue)
 
51
        c.Assert(storage.StateAttached(state), jc.IsTrue)
 
52
 
 
53
        state, ok = states[names.NewStorageTag("data/1")]
 
54
        c.Assert(ok, jc.IsTrue)
 
55
        c.Assert(storage.StateAttached(state), jc.IsFalse)
 
56
}
 
57
 
 
58
func (s *stateSuite) TestReadAllStateFilesJunk(c *gc.C) {
 
59
        dir := c.MkDir()
 
60
        writeFile(c, filepath.Join(dir, "data-0"), "attached: true")
 
61
        // data-extra-1 is not a valid storage ID, so it will
 
62
        // be ignored by ReadAllStateFiles.
 
63
        writeFile(c, filepath.Join(dir, "data-extra-1"), "attached: false")
 
64
        // subdirs are ignored.
 
65
        err := os.Mkdir(filepath.Join(dir, "data-1"), 0755)
 
66
        c.Assert(err, jc.ErrorIsNil)
 
67
 
 
68
        states, err := storage.ReadAllStateFiles(dir)
 
69
        c.Assert(err, jc.ErrorIsNil)
 
70
        c.Assert(states, gc.HasLen, 1)
 
71
        _, ok := states[names.NewStorageTag("data/0")]
 
72
        c.Assert(ok, jc.IsTrue)
 
73
}
 
74
 
 
75
func (s *stateSuite) TestReadAllStateFilesOneBadApple(c *gc.C) {
 
76
        dir := c.MkDir()
 
77
        writeFile(c, filepath.Join(dir, "data-0"), "rubbish")
 
78
        _, err := storage.ReadAllStateFiles(dir)
 
79
        c.Assert(err, gc.ErrorMatches, `cannot load storage state from ".*": cannot load storage "data/0" state from ".*": invalid storage state file ".*": missing 'attached'`)
 
80
}
 
81
 
 
82
func (s *stateSuite) TestReadAllStateFilesDirNotExist(c *gc.C) {
 
83
        dir := filepath.Join(c.MkDir(), "doesnotexist")
 
84
        states, err := storage.ReadAllStateFiles(dir)
 
85
        c.Assert(err, jc.ErrorIsNil)
 
86
        c.Assert(states, gc.HasLen, 0)
 
87
}
 
88
 
 
89
func (s *stateSuite) TestReadAllStateFilesDirEmpty(c *gc.C) {
 
90
        dir := c.MkDir()
 
91
        states, err := storage.ReadAllStateFiles(dir)
 
92
        c.Assert(err, jc.ErrorIsNil)
 
93
        c.Assert(states, gc.HasLen, 0)
 
94
}
 
95
 
 
96
func (s *stateSuite) TestReadStateFileFileNotExist(c *gc.C) {
 
97
        dir := c.MkDir()
 
98
        state, err := storage.ReadStateFile(dir, names.NewStorageTag("data/0"))
 
99
        c.Assert(err, jc.ErrorIsNil)
 
100
        c.Assert(state, gc.NotNil)
 
101
 
 
102
        data, err := ioutil.ReadFile(filepath.Join(dir, "data-0"))
 
103
        c.Assert(err, jc.Satisfies, os.IsNotExist)
 
104
 
 
105
        err = state.CommitHook(hook.Info{
 
106
                Kind:      hooks.StorageAttached,
 
107
                StorageId: "data-0",
 
108
        })
 
109
        c.Assert(err, jc.ErrorIsNil)
 
110
 
 
111
        data, err = ioutil.ReadFile(filepath.Join(dir, "data-0"))
 
112
        c.Assert(err, jc.ErrorIsNil)
 
113
        c.Assert(string(data), gc.Equals, "attached: true\n")
 
114
}
 
115
 
 
116
func (s *stateSuite) TestReadStateFileDirNotExist(c *gc.C) {
 
117
        dir := filepath.Join(c.MkDir(), "doesnotexist")
 
118
        state, err := storage.ReadStateFile(dir, names.NewStorageTag("data/0"))
 
119
        c.Assert(err, jc.ErrorIsNil)
 
120
        c.Assert(state, gc.NotNil)
 
121
 
 
122
        // CommitHook will fail if the directory does not exist. The uniter
 
123
        // must ensure the directory is created before committing any hooks
 
124
        // to the storage state.
 
125
        err = state.CommitHook(hook.Info{
 
126
                Kind:      hooks.StorageAttached,
 
127
                StorageId: "data-0",
 
128
        })
 
129
        c.Assert(errors.Cause(err), jc.Satisfies, os.IsNotExist)
 
130
}
 
131
 
 
132
func (s *stateSuite) TestReadStateFileBadFormat(c *gc.C) {
 
133
        dir := c.MkDir()
 
134
        writeFile(c, filepath.Join(dir, "data-0"), "!@#")
 
135
        _, err := storage.ReadStateFile(dir, names.NewStorageTag("data/0"))
 
136
        c.Assert(err, gc.ErrorMatches, `cannot load storage "data/0" state from ".*": invalid storage state file ".*": YAML error: did not find expected whitespace or line break`)
 
137
 
 
138
        writeFile(c, filepath.Join(dir, "data-0"), "icantbelieveitsnotattached: true\n")
 
139
        _, err = storage.ReadStateFile(dir, names.NewStorageTag("data/0"))
 
140
        c.Assert(err, gc.ErrorMatches, `cannot load storage "data/0" state from ".*": invalid storage state file ".*": missing 'attached'`)
 
141
}
 
142
 
 
143
func (s *stateSuite) TestCommitHook(c *gc.C) {
 
144
        dir := c.MkDir()
 
145
        state, err := storage.ReadStateFile(dir, names.NewStorageTag("data/0"))
 
146
        c.Assert(err, jc.ErrorIsNil)
 
147
        c.Assert(state, gc.NotNil)
 
148
        stateFile := filepath.Join(dir, "data-0")
 
149
 
 
150
        // CommitHook must be idempotent, so test each operation
 
151
        // twice in a row.
 
152
 
 
153
        for i := 0; i < 2; i++ {
 
154
                err := state.CommitHook(hook.Info{
 
155
                        Kind:      hooks.StorageAttached,
 
156
                        StorageId: "data-0",
 
157
                })
 
158
                c.Assert(err, jc.ErrorIsNil)
 
159
                c.Assert(stateFile, jc.IsNonEmptyFile)
 
160
        }
 
161
 
 
162
        for i := 0; i < 2; i++ {
 
163
                err := state.CommitHook(hook.Info{
 
164
                        Kind:      hooks.StorageDetaching,
 
165
                        StorageId: "data-0",
 
166
                })
 
167
                c.Assert(err, jc.ErrorIsNil)
 
168
                c.Assert(stateFile, jc.DoesNotExist)
 
169
        }
 
170
}
 
171
 
 
172
func (s *stateSuite) TestValidateHook(c *gc.C) {
 
173
        const unattached = false
 
174
        const attached = true
 
175
 
 
176
        err := storage.ValidateHook(
 
177
                names.NewStorageTag("data/0"), unattached,
 
178
                hook.Info{Kind: hooks.StorageAttached, StorageId: "data/1"},
 
179
        )
 
180
        c.Assert(err, gc.ErrorMatches, `inappropriate "storage-attached" hook for storage "data/0": expected storage "data/0", got storage "data/1"`)
 
181
 
 
182
        validate := func(attached bool, kind hooks.Kind) error {
 
183
                return storage.ValidateHook(
 
184
                        names.NewStorageTag("data/0"), attached,
 
185
                        hook.Info{Kind: kind, StorageId: "data/0"},
 
186
                )
 
187
        }
 
188
        assertValidates := func(attached bool, kind hooks.Kind) {
 
189
                err := validate(attached, kind)
 
190
                c.Assert(err, jc.ErrorIsNil)
 
191
        }
 
192
        assertValidateFails := func(attached bool, kind hooks.Kind, expect string) {
 
193
                err := validate(attached, kind)
 
194
                c.Assert(err, gc.ErrorMatches, expect)
 
195
        }
 
196
 
 
197
        assertValidates(false, hooks.StorageAttached)
 
198
        assertValidates(true, hooks.StorageDetaching)
 
199
        assertValidateFails(false, hooks.StorageDetaching, `inappropriate "storage-detaching" hook for storage "data/0": storage not attached`)
 
200
        assertValidateFails(true, hooks.StorageAttached, `inappropriate "storage-attached" hook for storage "data/0": storage already attached`)
 
201
}