github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/space/package_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 "net" 8 "regexp" 9 stdtesting "testing" 10 11 "github.com/juju/cmd" 12 "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/utils/featureflag" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/apiserver/params" 18 "github.com/juju/juju/cmd/juju/space" 19 "github.com/juju/juju/feature" 20 coretesting "github.com/juju/juju/testing" 21 ) 22 23 func TestPackage(t *stdtesting.T) { 24 gc.TestingT(t) 25 } 26 27 // BaseSpaceSuite is used for embedding in other suites. 28 type BaseSpaceSuite struct { 29 coretesting.FakeJujuHomeSuite 30 coretesting.BaseSuite 31 32 superCmd cmd.Command 33 command cmd.Command 34 api *StubAPI 35 } 36 37 var _ = gc.Suite(&BaseSpaceSuite{}) 38 39 func (s *BaseSpaceSuite) SetUpTest(c *gc.C) { 40 // If any post-MVP command suite enabled the flag, keep it. 41 hasFeatureFlag := featureflag.Enabled(feature.PostNetCLIMVP) 42 43 s.BaseSuite.SetUpTest(c) 44 s.FakeJujuHomeSuite.SetUpTest(c) 45 46 if hasFeatureFlag { 47 s.BaseSuite.SetFeatureFlags(feature.PostNetCLIMVP) 48 } 49 50 s.superCmd = space.NewSuperCommand() 51 c.Assert(s.superCmd, gc.NotNil) 52 53 s.api = NewStubAPI() 54 c.Assert(s.api, gc.NotNil) 55 56 // All subcommand suites embedding this one should initialize 57 // s.command immediately after calling this method! 58 } 59 60 // RunSuperCommand executes the super command passing any args and 61 // returning the stdout and stderr output as strings, as well as any 62 // error. If s.command is set, the subcommand's name will be passed as 63 // first argument. 64 func (s *BaseSpaceSuite) RunSuperCommand(c *gc.C, args ...string) (string, string, error) { 65 if s.command != nil { 66 args = append([]string{s.command.Info().Name}, args...) 67 } 68 ctx, err := coretesting.RunCommand(c, s.superCmd, args...) 69 if ctx != nil { 70 return coretesting.Stdout(ctx), coretesting.Stderr(ctx), err 71 } 72 return "", "", err 73 } 74 75 // RunSubCommand executes the s.command subcommand passing any args 76 // and returning the stdout and stderr output as strings, as well as 77 // any error. 78 func (s *BaseSpaceSuite) RunSubCommand(c *gc.C, args ...string) (string, string, error) { 79 if s.command == nil { 80 panic("subcommand is nil") 81 } 82 ctx, err := coretesting.RunCommand(c, s.command, args...) 83 if ctx != nil { 84 return coretesting.Stdout(ctx), coretesting.Stderr(ctx), err 85 } 86 return "", "", err 87 } 88 89 // AssertRunFails is a shortcut for calling RunSubCommand with the 90 // passed args then asserting the output is empty and the error is as 91 // expected, finally returning the error. 92 func (s *BaseSpaceSuite) AssertRunFails(c *gc.C, expectErr string, args ...string) error { 93 stdout, stderr, err := s.RunSubCommand(c, args...) 94 c.Assert(err, gc.ErrorMatches, expectErr) 95 c.Assert(stdout, gc.Equals, "") 96 c.Assert(stderr, gc.Equals, "") 97 return err 98 } 99 100 // AssertRunSucceeds is a shortcut for calling RunSuperCommand with 101 // the passed args then asserting the stderr output matches 102 // expectStderr, stdout is equal to expectStdout, and the error is 103 // nil. 104 func (s *BaseSpaceSuite) AssertRunSucceeds(c *gc.C, expectStderr, expectStdout string, args ...string) { 105 stdout, stderr, err := s.RunSubCommand(c, args...) 106 c.Assert(err, jc.ErrorIsNil) 107 c.Assert(stdout, gc.Equals, expectStdout) 108 c.Assert(stderr, gc.Matches, expectStderr) 109 } 110 111 // TestHelp runs the command with --help as argument and verifies the 112 // output. 113 func (s *BaseSpaceSuite) TestHelp(c *gc.C) { 114 stderr, stdout, err := s.RunSuperCommand(c, "--help") 115 c.Assert(err, jc.ErrorIsNil) 116 c.Check(stdout, gc.Equals, "") 117 c.Check(stderr, gc.Not(gc.Equals), "") 118 119 // If s.command is set, use it instead of s.superCmd. 120 cmdInfo := s.superCmd.Info() 121 var expected string 122 if s.command != nil { 123 // Subcommands embed EnvCommandBase 124 cmdInfo = s.command.Info() 125 expected = "(?sm).*^usage: juju space " + 126 regexp.QuoteMeta(cmdInfo.Name) + 127 `( \[options\])? ` + regexp.QuoteMeta(cmdInfo.Args) + ".+" 128 } else { 129 expected = "(?sm).*^usage: juju space" + 130 `( \[options\])? ` + regexp.QuoteMeta(cmdInfo.Args) + ".+" 131 } 132 c.Check(cmdInfo, gc.NotNil) 133 c.Check(stderr, gc.Matches, expected) 134 135 expected = "(?sm).*^purpose: " + regexp.QuoteMeta(cmdInfo.Purpose) + "$.*" 136 c.Check(stderr, gc.Matches, expected) 137 138 expected = "(?sm).*^" + regexp.QuoteMeta(cmdInfo.Doc) + "$.*" 139 c.Check(stderr, gc.Matches, expected) 140 } 141 142 // Strings is makes tests taking a slice of strings slightly easier to 143 // write: e.g. s.Strings("foo", "bar") vs. []string{"foo", "bar"}. 144 func (s *BaseSpaceSuite) Strings(values ...string) []string { 145 return values 146 } 147 148 // StubAPI defines a testing stub for the SpaceAPI interface. 149 type StubAPI struct { 150 *testing.Stub 151 152 Spaces []params.Space 153 Subnets []params.Subnet 154 } 155 156 var _ space.SpaceAPI = (*StubAPI)(nil) 157 158 // NewStubAPI creates a StubAPI suitable for passing to 159 // space.New*Command(). 160 func NewStubAPI() *StubAPI { 161 subnets := []params.Subnet{{ 162 // IPv6 subnet. 163 CIDR: "2001:db8::/32", 164 ProviderId: "subnet-public", 165 Life: params.Dying, 166 SpaceTag: "space-space1", 167 Zones: []string{"zone2"}, 168 }, { 169 // Invalid subnet (just for 100% coverage, otherwise it can't happen). 170 CIDR: "invalid", 171 ProviderId: "no-such", 172 SpaceTag: "space-space1", 173 Zones: []string{"zone1"}, 174 }, { 175 // IPv4 subnet. 176 CIDR: "10.1.2.0/24", 177 ProviderId: "subnet-private", 178 Life: params.Alive, 179 SpaceTag: "space-space2", 180 Zones: []string{"zone1", "zone2"}, 181 StaticRangeLowIP: net.ParseIP("10.1.2.10"), 182 StaticRangeHighIP: net.ParseIP("10.1.2.200"), 183 }, { 184 // IPv4 VLAN subnet. 185 CIDR: "4.3.2.0/28", 186 Life: params.Dead, 187 ProviderId: "vlan-42", 188 SpaceTag: "space-space2", 189 Zones: []string{"zone1"}, 190 VLANTag: 42, 191 StaticRangeLowIP: net.ParseIP("4.3.2.2"), 192 StaticRangeHighIP: net.ParseIP("4.3.2.4"), 193 }} 194 spaces := []params.Space{{ 195 Name: "space1", 196 Subnets: append([]params.Subnet{}, subnets[:2]...), 197 }, { 198 Name: "space2", 199 Subnets: append([]params.Subnet{}, subnets[2:]...), 200 }} 201 return &StubAPI{ 202 Stub: &testing.Stub{}, 203 Spaces: spaces, 204 Subnets: subnets, 205 } 206 } 207 208 func (sa *StubAPI) Close() error { 209 sa.MethodCall(sa, "Close") 210 return sa.NextErr() 211 } 212 213 func (sa *StubAPI) ListSpaces() ([]params.Space, error) { 214 sa.MethodCall(sa, "ListSpaces") 215 if err := sa.NextErr(); err != nil { 216 return nil, err 217 } 218 return sa.Spaces, nil 219 } 220 221 func (sa *StubAPI) CreateSpace(name string, subnetIds []string, public bool) error { 222 sa.MethodCall(sa, "CreateSpace", name, subnetIds, public) 223 return sa.NextErr() 224 } 225 226 func (sa *StubAPI) RemoveSpace(name string) error { 227 sa.MethodCall(sa, "RemoveSpace", name) 228 return sa.NextErr() 229 } 230 231 func (sa *StubAPI) UpdateSpace(name string, subnetIds []string) error { 232 sa.MethodCall(sa, "UpdateSpace", name, subnetIds) 233 return sa.NextErr() 234 } 235 236 func (sa *StubAPI) RenameSpace(name, newName string) error { 237 sa.MethodCall(sa, "RenameSpace", name, newName) 238 return sa.NextErr() 239 }