1
// Copyright 2012-2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
4
package application_test
14
jc "github.com/juju/testing/checkers"
15
"github.com/juju/utils"
16
gc "gopkg.in/check.v1"
18
"github.com/juju/juju/apiserver/common"
19
"github.com/juju/juju/cmd/juju/application"
20
coretesting "github.com/juju/juju/testing"
23
type SetSuite struct {
24
coretesting.FakeJujuXDGDataHomeSuite
26
fakeServiceAPI *fakeServiceAPI
29
var _ = gc.Suite(&SetSuite{})
32
validSetTestValue = "a value with spaces\nand newline\nand UTF-8 characters: \U0001F604 / \U0001F44D"
33
invalidSetTestValue = "a value with an invalid UTF-8 sequence: " + string([]byte{0xFF, 0xFF})
34
yamlConfigValue = "dummy-application:\n skill-level: 9000\n username: admin001\n\n"
37
func (s *SetSuite) SetUpTest(c *gc.C) {
38
s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
39
s.fakeServiceAPI = &fakeServiceAPI{serviceName: "dummy-application"}
42
c.Assert(utf8.ValidString(validSetTestValue), jc.IsTrue)
43
c.Assert(utf8.ValidString(invalidSetTestValue), jc.IsFalse)
44
setupValueFile(c, s.dir, "valid.txt", validSetTestValue)
45
setupValueFile(c, s.dir, "invalid.txt", invalidSetTestValue)
46
setupBigFile(c, s.dir)
47
setupConfigFile(c, s.dir)
50
func (s *SetSuite) TestSetCommandInit(c *gc.C) {
52
err := coretesting.InitCommand(application.NewSetCommandForTest(s.fakeServiceAPI), []string{})
53
c.Assert(err, gc.ErrorMatches, "no application name specified")
55
// missing application name
56
err = coretesting.InitCommand(application.NewSetCommandForTest(s.fakeServiceAPI), []string{"name=foo"})
57
c.Assert(err, gc.ErrorMatches, "no application name specified")
59
// --config path, but no application
60
err = coretesting.InitCommand(application.NewSetCommandForTest(s.fakeServiceAPI), []string{"--config", "testconfig.yaml"})
61
c.Assert(err, gc.ErrorMatches, "no application name specified")
63
// --config and options specified
64
err = coretesting.InitCommand(application.NewSetCommandForTest(s.fakeServiceAPI), []string{"application", "--config", "testconfig.yaml", "bees="})
65
c.Assert(err, gc.ErrorMatches, "cannot specify --config when using key=value arguments")
67
// --to-default and no config name provided
68
err = coretesting.InitCommand(application.NewSetCommandForTest(s.fakeServiceAPI), []string{"application", "--to-default"})
69
c.Assert(err, gc.ErrorMatches, "no configuration options specified")
73
func (s *SetSuite) TestSetOptionSuccess(c *gc.C) {
74
s.assertSetSuccess(c, s.dir, []string{
76
"outlook=hello@world.tld",
77
}, map[string]interface{}{
79
"outlook": "hello@world.tld",
81
s.assertSetSuccess(c, s.dir, []string{
83
}, map[string]interface{}{
84
"username": "hello=foo",
85
"outlook": "hello@world.tld",
87
s.assertSetSuccess(c, s.dir, []string{
88
"username=@valid.txt",
89
}, map[string]interface{}{
90
"username": validSetTestValue,
91
"outlook": "hello@world.tld",
93
s.assertSetSuccess(c, s.dir, []string{
95
}, map[string]interface{}{
97
"outlook": "hello@world.tld",
101
func (s *SetSuite) TestSetSameValue(c *gc.C) {
102
s.assertSetSuccess(c, s.dir, []string{
104
"outlook=hello@world.tld",
105
}, map[string]interface{}{
107
"outlook": "hello@world.tld",
109
s.assertSetWarning(c, s.dir, []string{
111
}, "the configuration setting \"username\" already has the value \"hello\"")
112
s.assertSetWarning(c, s.dir, []string{
113
"outlook=hello@world.tld",
114
}, "the configuration setting \"outlook\" already has the value \"hello@world.tld\"")
118
func (s *SetSuite) TestSetOptionFail(c *gc.C) {
119
s.assertSetFail(c, s.dir, []string{"foo", "bar"}, "error: expected \"key=value\", got \"foo\"\n")
120
s.assertSetFail(c, s.dir, []string{"=bar"}, "error: expected \"key=value\", got \"=bar\"\n")
121
s.assertSetFail(c, s.dir, []string{
122
"username=@missing.txt",
123
}, "error: cannot read option from file \"missing.txt\": .* "+utils.NoSuchFileErrRegexp+"\n")
124
s.assertSetFail(c, s.dir, []string{
126
}, "error: size of option file is larger than 5M\n")
127
s.assertSetFail(c, s.dir, []string{
128
"username=@invalid.txt",
129
}, "error: value for option \"username\" contains non-UTF-8 sequences\n")
132
func (s *SetSuite) TestSetConfig(c *gc.C) {
133
s.assertSetFail(c, s.dir, []string{
136
}, "error.* "+utils.NoSuchFileErrRegexp+"\n")
138
ctx := coretesting.ContextForDir(c, s.dir)
139
code := cmd.Main(application.NewSetCommandForTest(s.fakeServiceAPI), ctx, []string{
144
c.Check(code, gc.Equals, 0)
145
c.Check(s.fakeServiceAPI.config, gc.Equals, yamlConfigValue)
148
func (s *SetSuite) TestSetConfigToDefault(c *gc.C) {
149
s.fakeServiceAPI = &fakeServiceAPI{serviceName: "dummy-application", values: map[string]interface{}{
152
s.assertSetSuccess(c, s.dir, []string{
155
}, make(map[string]interface{}))
158
func (s *SetSuite) TestBlockSetConfig(c *gc.C) {
160
s.fakeServiceAPI.err = common.OperationBlockedError("TestBlockSetConfig")
161
ctx := coretesting.ContextForDir(c, s.dir)
162
code := cmd.Main(application.NewSetCommandForTest(s.fakeServiceAPI), ctx, []string{
166
c.Check(code, gc.Equals, 1)
168
stripped := strings.Replace(c.GetTestLog(), "\n", "", -1)
169
c.Check(stripped, gc.Matches, ".*TestBlockSetConfig.*")
172
// assertSetSuccess sets configuration options and checks the expected settings.
173
func (s *SetSuite) assertSetSuccess(c *gc.C, dir string, args []string, expect map[string]interface{}) {
174
ctx := coretesting.ContextForDir(c, dir)
175
code := cmd.Main(application.NewSetCommandForTest(s.fakeServiceAPI), ctx, append([]string{"dummy-application"}, args...))
176
c.Assert(code, gc.Equals, 0)
179
// assertSetFail sets configuration options and checks the expected error.
180
func (s *SetSuite) assertSetFail(c *gc.C, dir string, args []string, err string) {
181
ctx := coretesting.ContextForDir(c, dir)
182
code := cmd.Main(application.NewSetCommandForTest(s.fakeServiceAPI), ctx, append([]string{"dummy-application"}, args...))
183
c.Check(code, gc.Not(gc.Equals), 0)
184
c.Assert(ctx.Stderr.(*bytes.Buffer).String(), gc.Matches, err)
187
func (s *SetSuite) assertSetWarning(c *gc.C, dir string, args []string, w string) {
188
ctx := coretesting.ContextForDir(c, dir)
189
code := cmd.Main(application.NewSetCommandForTest(s.fakeServiceAPI), ctx, append([]string{"dummy-application"}, args...))
190
c.Check(code, gc.Equals, 0)
192
c.Assert(strings.Replace(c.GetTestLog(), "\n", " ", -1), gc.Matches, ".*WARNING.*"+w+".*")
195
// setupValueFile creates a file containing one value for testing
196
// set with name=@filename.
197
func setupValueFile(c *gc.C, dir, filename, value string) string {
198
ctx := coretesting.ContextForDir(c, dir)
199
path := ctx.AbsPath(filename)
200
content := []byte(value)
201
err := ioutil.WriteFile(path, content, 0666)
202
c.Assert(err, jc.ErrorIsNil)
206
// setupBigFile creates a too big file for testing
207
// set with name=@filename.
208
func setupBigFile(c *gc.C, dir string) string {
209
ctx := coretesting.ContextForDir(c, dir)
210
path := ctx.AbsPath("big.txt")
211
file, err := os.Create(path)
212
c.Assert(err, jc.ErrorIsNil)
214
chunk := make([]byte, 1024)
215
for i := 0; i < cap(chunk); i++ {
216
chunk[i] = byte(i % 256)
218
for i := 0; i < 6000; i++ {
219
_, err = file.Write(chunk)
220
c.Assert(err, jc.ErrorIsNil)
225
// setupConfigFile creates a configuration file for testing set
226
// with the --config argument specifying a configuration file.
227
func setupConfigFile(c *gc.C, dir string) string {
228
ctx := coretesting.ContextForDir(c, dir)
229
path := ctx.AbsPath("testconfig.yaml")
230
content := []byte(yamlConfigValue)
231
err := ioutil.WriteFile(path, content, 0666)
232
c.Assert(err, jc.ErrorIsNil)