github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/space/list_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package space_test 5 6 import ( 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 12 "regexp" 13 14 "github.com/juju/errors" 15 jc "github.com/juju/testing/checkers" 16 gc "gopkg.in/check.v1" 17 18 "github.com/juju/juju/cmd/juju/space" 19 coretesting "github.com/juju/juju/testing" 20 ) 21 22 type ListSuite struct { 23 BaseSpaceSuite 24 } 25 26 var _ = gc.Suite(&ListSuite{}) 27 28 func (s *ListSuite) SetUpTest(c *gc.C) { 29 s.BaseSpaceSuite.SetUpTest(c) 30 s.command, _ = space.NewListCommandForTest(s.api) 31 c.Assert(s.command, gc.NotNil) 32 } 33 34 func (s *ListSuite) TestInit(c *gc.C) { 35 for i, test := range []struct { 36 about string 37 args []string 38 expectShort bool 39 expectFormat string 40 expectErr string 41 }{{ 42 about: "unrecognized arguments", 43 args: s.Strings("foo"), 44 expectErr: `unrecognized args: \["foo"\]`, 45 expectFormat: "yaml", 46 }, { 47 about: "invalid format", 48 args: s.Strings("--format", "foo"), 49 expectErr: `invalid value "foo" for flag --format: unknown format "foo"`, 50 expectFormat: "yaml", 51 }, { 52 about: "invalid format (value is case-sensitive)", 53 args: s.Strings("--format", "JSON"), 54 expectErr: `invalid value "JSON" for flag --format: unknown format "JSON"`, 55 expectFormat: "yaml", 56 }, { 57 about: "json format", 58 args: s.Strings("--format", "json"), 59 expectFormat: "json", 60 }, { 61 about: "yaml format", 62 args: s.Strings("--format", "yaml"), 63 expectFormat: "yaml", 64 }, { 65 // --output and -o are tested separately in TestOutputFormats. 66 about: "both --output and -o specified (latter overrides former)", 67 args: s.Strings("--output", "foo", "-o", "bar"), 68 expectFormat: "yaml", 69 }} { 70 c.Logf("test #%d: %s", i, test.about) 71 // Create a new instance of the subcommand for each test, but 72 // since we're not running the command no need to use 73 // modelcmd.Wrap(). 74 wrappedCommand, command := space.NewListCommandForTest(s.api) 75 err := coretesting.InitCommand(wrappedCommand, test.args) 76 if test.expectErr != "" { 77 c.Check(err, gc.ErrorMatches, test.expectErr) 78 } else { 79 c.Check(err, jc.ErrorIsNil) 80 } 81 c.Check(command.ListFormat(), gc.Equals, test.expectFormat) 82 c.Check(command.Short, gc.Equals, test.expectShort) 83 84 // No API calls should be recorded at this stage. 85 s.api.CheckCallNames(c) 86 } 87 } 88 89 func (s *ListSuite) TestOutputFormats(c *gc.C) { 90 outDir := c.MkDir() 91 expectedYAML := ` 92 spaces: 93 space1: 94 2001:db8::/32: 95 type: ipv6 96 provider-id: subnet-public 97 status: terminating 98 zones: 99 - zone2 100 invalid: 101 type: unknown 102 provider-id: no-such 103 status: 'error: invalid subnet CIDR: invalid' 104 zones: 105 - zone1 106 space2: 107 4.3.2.0/28: 108 type: ipv4 109 provider-id: vlan-42 110 status: terminating 111 zones: 112 - zone1 113 10.1.2.0/24: 114 type: ipv4 115 provider-id: subnet-private 116 status: in-use 117 zones: 118 - zone1 119 - zone2 120 `[1:] 121 unwrap := regexp.MustCompile(`[\s+\n]`) 122 expectedJSON := unwrap.ReplaceAllLiteralString(` 123 { 124 "spaces": { 125 "space1": { 126 "2001:db8::/32": { 127 "type": "ipv6", 128 "provider-id": "subnet-public", 129 "status": "terminating", 130 "zones": ["zone2"] 131 }, 132 "invalid": { 133 "type": "unknown", 134 "provider-id": "no-such", 135 "status": "error: invalid subnet CIDR: invalid", 136 "zones": ["zone1"] 137 } 138 }, 139 "space2": { 140 "10.1.2.0/24": { 141 "type": "ipv4", 142 "provider-id": "subnet-private", 143 "status": "in-use", 144 "zones": ["zone1","zone2"] 145 }, 146 "4.3.2.0/28": { 147 "type": "ipv4", 148 "provider-id": "vlan-42", 149 "status": "terminating", 150 "zones": ["zone1"] 151 } 152 } 153 } 154 } 155 `, "") + "\n" 156 // Work around the big unwrap hammer above. 157 expectedJSON = strings.Replace( 158 expectedJSON, 159 "error:invalidsubnetCIDR:invalid", 160 "error: invalid subnet CIDR: invalid", 161 1, 162 ) 163 expectedShortYAML := ` 164 spaces: 165 - space1 166 - space2 167 `[1:] 168 169 expectedShortJSON := unwrap.ReplaceAllLiteralString(` 170 { 171 "spaces": [ 172 "space1", 173 "space2" 174 ] 175 } 176 `, "") + "\n" 177 178 assertAPICalls := func() { 179 // Verify the API calls and reset the recorded calls. 180 s.api.CheckCallNames(c, "ListSpaces", "Close") 181 s.api.ResetCalls() 182 } 183 makeArgs := func(format string, short bool, extraArgs ...string) []string { 184 args := s.Strings(extraArgs...) 185 if format != "" { 186 args = append(args, "--format", format) 187 } 188 if short == true { 189 args = append(args, "--short") 190 } 191 return args 192 } 193 assertOutput := func(format, expected string, short bool) { 194 outFile := filepath.Join(outDir, "output") 195 c.Assert(outFile, jc.DoesNotExist) 196 defer os.Remove(outFile) 197 // Check -o works. 198 var args []string 199 args = makeArgs(format, short, "-o", outFile) 200 s.AssertRunSucceeds(c, "", "", args...) 201 assertAPICalls() 202 203 data, err := ioutil.ReadFile(outFile) 204 c.Assert(err, jc.ErrorIsNil) 205 c.Assert(string(data), gc.Equals, expected) 206 207 // Check the last output argument takes precedence when both 208 // -o and --output are given (and also that --output works the 209 // same as -o). 210 outFile1 := filepath.Join(outDir, "output1") 211 c.Assert(outFile1, jc.DoesNotExist) 212 defer os.Remove(outFile1) 213 outFile2 := filepath.Join(outDir, "output2") 214 c.Assert(outFile2, jc.DoesNotExist) 215 defer os.Remove(outFile2) 216 // Write something in outFile2 to verify its contents are 217 // overwritten. 218 err = ioutil.WriteFile(outFile2, []byte("some contents"), 0644) 219 c.Assert(err, jc.ErrorIsNil) 220 221 args = makeArgs(format, short, "-o", outFile1, "--output", outFile2) 222 s.AssertRunSucceeds(c, "", "", args...) 223 // Check only the last output file was used, and the output 224 // file was overwritten. 225 c.Assert(outFile1, jc.DoesNotExist) 226 data, err = ioutil.ReadFile(outFile2) 227 c.Assert(err, jc.ErrorIsNil) 228 c.Assert(string(data), gc.Equals, expected) 229 assertAPICalls() 230 231 // Finally, check without --output. 232 args = makeArgs(format, short) 233 s.AssertRunSucceeds(c, "", expected, args...) 234 assertAPICalls() 235 } 236 237 for i, test := range []struct { 238 format string 239 expected string 240 short bool 241 }{ 242 {"", expectedYAML, false}, // default format is YAML 243 {"yaml", expectedYAML, false}, 244 {"json", expectedJSON, false}, 245 {"", expectedShortYAML, true}, // default format is YAML 246 {"yaml", expectedShortYAML, true}, 247 {"json", expectedShortJSON, true}, 248 } { 249 c.Logf("test #%d: format %q, short %v", i, test.format, test.short) 250 assertOutput(test.format, test.expected, test.short) 251 } 252 } 253 254 func (s *ListSuite) TestRunWhenNoSpacesExistSucceeds(c *gc.C) { 255 s.api.Spaces = s.api.Spaces[0:0] 256 257 s.AssertRunSucceeds(c, 258 `no spaces to display\n`, 259 "", // empty stdout. 260 ) 261 262 s.api.CheckCallNames(c, "ListSpaces", "Close") 263 s.api.CheckCall(c, 0, "ListSpaces") 264 } 265 266 func (s *ListSuite) TestRunWhenSpacesNotSupported(c *gc.C) { 267 s.api.SetErrors(errors.NewNotSupported(nil, "spaces not supported")) 268 269 err := s.AssertRunSpacesNotSupported(c, "cannot list spaces: spaces not supported") 270 c.Assert(err, jc.Satisfies, errors.IsNotSupported) 271 272 s.api.CheckCallNames(c, "ListSpaces", "Close") 273 s.api.CheckCall(c, 0, "ListSpaces") 274 } 275 276 func (s *ListSuite) TestRunWhenSpacesAPIFails(c *gc.C) { 277 s.api.SetErrors(errors.New("boom")) 278 279 s.AssertRunFails(c, "cannot list spaces: boom") 280 281 s.api.CheckCallNames(c, "ListSpaces", "Close") 282 s.api.CheckCall(c, 0, "ListSpaces") 283 }