github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/juju/subnet/package_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package subnet_test 5 6 import ( 7 "net" 8 "regexp" 9 stdtesting "testing" 10 11 "github.com/juju/cmd" 12 "github.com/juju/names" 13 "github.com/juju/testing" 14 jc "github.com/juju/testing/checkers" 15 "github.com/juju/utils/featureflag" 16 gc "gopkg.in/check.v1" 17 18 "github.com/juju/juju/apiserver/params" 19 "github.com/juju/juju/cmd/juju/subnet" 20 "github.com/juju/juju/feature" 21 "github.com/juju/juju/network" 22 coretesting "github.com/juju/juju/testing" 23 ) 24 25 func TestPackage(t *stdtesting.T) { 26 gc.TestingT(t) 27 } 28 29 // BaseSubnetSuite is used for embedding in other suites. 30 type BaseSubnetSuite struct { 31 coretesting.FakeJujuHomeSuite 32 coretesting.BaseSuite 33 34 superCmd cmd.Command 35 command cmd.Command 36 api *StubAPI 37 } 38 39 var _ = gc.Suite(&BaseSubnetSuite{}) 40 41 func (s *BaseSubnetSuite) SetUpTest(c *gc.C) { 42 // If any post-MVP command suite enabled the flag, keep it. 43 hasFeatureFlag := featureflag.Enabled(feature.PostNetCLIMVP) 44 45 s.BaseSuite.SetUpTest(c) 46 s.FakeJujuHomeSuite.SetUpTest(c) 47 48 if hasFeatureFlag { 49 s.BaseSuite.SetFeatureFlags(feature.PostNetCLIMVP) 50 } 51 52 s.superCmd = subnet.NewSuperCommand() 53 c.Assert(s.superCmd, gc.NotNil) 54 55 s.api = NewStubAPI() 56 c.Assert(s.api, gc.NotNil) 57 58 // All subcommand suites embedding this one should initialize 59 // s.command immediately after calling this method! 60 } 61 62 // RunSuperCommand executes the super command passing any args and 63 // returning the stdout and stderr output as strings, as well as any 64 // error. If s.command is set, the subcommand's name will be passed as 65 // first argument. 66 func (s *BaseSubnetSuite) RunSuperCommand(c *gc.C, args ...string) (string, string, error) { 67 if s.command != nil { 68 args = append([]string{s.command.Info().Name}, args...) 69 } 70 ctx, err := coretesting.RunCommand(c, s.superCmd, args...) 71 if ctx != nil { 72 return coretesting.Stdout(ctx), coretesting.Stderr(ctx), err 73 } 74 return "", "", err 75 } 76 77 // RunSubCommand executes the s.command subcommand passing any args 78 // and returning the stdout and stderr output as strings, as well as 79 // any error. 80 func (s *BaseSubnetSuite) RunSubCommand(c *gc.C, args ...string) (string, string, error) { 81 if s.command == nil { 82 panic("subcommand is nil") 83 } 84 ctx, err := coretesting.RunCommand(c, s.command, args...) 85 if ctx != nil { 86 return coretesting.Stdout(ctx), coretesting.Stderr(ctx), err 87 } 88 return "", "", err 89 } 90 91 // AssertRunFails is a shortcut for calling RunSubCommand with the 92 // passed args then asserting the output is empty and the error is as 93 // expected, finally returning the error. 94 func (s *BaseSubnetSuite) AssertRunFails(c *gc.C, expectErr string, args ...string) error { 95 stdout, stderr, err := s.RunSubCommand(c, args...) 96 c.Assert(err, gc.ErrorMatches, expectErr) 97 c.Assert(stdout, gc.Equals, "") 98 c.Assert(stderr, gc.Equals, "") 99 return err 100 } 101 102 // AssertRunSucceeds is a shortcut for calling RunSuperCommand with 103 // the passed args then asserting the stderr output matches 104 // expectStderr, stdout is equal to expectStdout, and the error is 105 // nil. 106 func (s *BaseSubnetSuite) AssertRunSucceeds(c *gc.C, expectStderr, expectStdout string, args ...string) { 107 stdout, stderr, err := s.RunSubCommand(c, args...) 108 c.Assert(err, jc.ErrorIsNil) 109 c.Assert(stdout, gc.Equals, expectStdout) 110 c.Assert(stderr, gc.Matches, expectStderr) 111 } 112 113 // TestHelp runs the command with --help as argument and verifies the 114 // output. 115 func (s *BaseSubnetSuite) TestHelp(c *gc.C) { 116 stderr, stdout, err := s.RunSuperCommand(c, "--help") 117 c.Assert(err, jc.ErrorIsNil) 118 c.Check(stdout, gc.Equals, "") 119 c.Check(stderr, gc.Not(gc.Equals), "") 120 121 // If s.command is set, use it instead of s.superCmd. 122 cmdInfo := s.superCmd.Info() 123 var expected string 124 if s.command != nil { 125 // Subcommands embed EnvCommandBase and have an extra 126 // "[options]" prepended before the args. 127 cmdInfo = s.command.Info() 128 expected = "(?sm).*^usage: juju subnet " + 129 regexp.QuoteMeta(cmdInfo.Name) + 130 `( \[options\])? ` + regexp.QuoteMeta(cmdInfo.Args) + ".+" 131 } else { 132 expected = "(?sm).*^usage: juju subnet" + 133 `( \[options\])? ` + regexp.QuoteMeta(cmdInfo.Args) + ".+" 134 } 135 c.Check(cmdInfo, gc.NotNil) 136 c.Check(stderr, gc.Matches, expected) 137 138 expected = "(?sm).*^purpose: " + regexp.QuoteMeta(cmdInfo.Purpose) + "$.*" 139 c.Check(stderr, gc.Matches, expected) 140 141 expected = "(?sm).*^" + regexp.QuoteMeta(cmdInfo.Doc) + "$.*" 142 c.Check(stderr, gc.Matches, expected) 143 } 144 145 // Strings makes tests taking a slice of strings slightly easier to 146 // write: e.g. s.Strings("foo", "bar") vs. []string{"foo", "bar"}. 147 func (s *BaseSubnetSuite) Strings(values ...string) []string { 148 return values 149 } 150 151 // StubAPI defines a testing stub for the SubnetAPI interface. 152 type StubAPI struct { 153 *testing.Stub 154 155 Subnets []params.Subnet 156 Spaces []names.Tag 157 Zones []string 158 } 159 160 var _ subnet.SubnetAPI = (*StubAPI)(nil) 161 162 // NewStubAPI creates a StubAPI suitable for passing to 163 // subnet.New*Command(). 164 func NewStubAPI() *StubAPI { 165 subnets := []params.Subnet{{ 166 // IPv4 subnet. 167 CIDR: "10.20.0.0/24", 168 ProviderId: "subnet-foo", 169 Life: params.Alive, 170 SpaceTag: "space-public", 171 Zones: []string{"zone1", "zone2"}, 172 StaticRangeLowIP: net.ParseIP("10.20.0.10"), 173 StaticRangeHighIP: net.ParseIP("10.20.0.100"), 174 }, { 175 // IPv6 subnet. 176 CIDR: "2001:db8::/32", 177 ProviderId: "subnet-bar", 178 Life: params.Dying, 179 SpaceTag: "space-dmz", 180 Zones: []string{"zone2"}, 181 }, { 182 // IPv4 VLAN subnet. 183 CIDR: "10.10.0.0/16", 184 Life: params.Dead, 185 SpaceTag: "space-vlan-42", 186 Zones: []string{"zone1"}, 187 VLANTag: 42, 188 }} 189 return &StubAPI{ 190 Stub: &testing.Stub{}, 191 Zones: []string{"zone1", "zone2"}, 192 Subnets: subnets, 193 Spaces: []names.Tag{ 194 names.NewSpaceTag("default"), 195 names.NewSpaceTag("public"), 196 names.NewSpaceTag("dmz"), 197 names.NewSpaceTag("vlan-42"), 198 }, 199 } 200 } 201 202 func (sa *StubAPI) Close() error { 203 sa.MethodCall(sa, "Close") 204 return sa.NextErr() 205 } 206 207 func (sa *StubAPI) AllZones() ([]string, error) { 208 sa.MethodCall(sa, "AllZones") 209 if err := sa.NextErr(); err != nil { 210 return nil, err 211 } 212 return sa.Zones, nil 213 } 214 215 func (sa *StubAPI) AllSpaces() ([]names.Tag, error) { 216 sa.MethodCall(sa, "AllSpaces") 217 if err := sa.NextErr(); err != nil { 218 return nil, err 219 } 220 return sa.Spaces, nil 221 } 222 223 func (sa *StubAPI) CreateSubnet(subnetCIDR names.SubnetTag, spaceTag names.SpaceTag, zones []string, isPublic bool) error { 224 sa.MethodCall(sa, "CreateSubnet", subnetCIDR, spaceTag, zones, isPublic) 225 return sa.NextErr() 226 } 227 228 func (sa *StubAPI) AddSubnet(cidr names.SubnetTag, id network.Id, spaceTag names.SpaceTag, zones []string) error { 229 sa.MethodCall(sa, "AddSubnet", cidr, id, spaceTag, zones) 230 return sa.NextErr() 231 } 232 233 func (sa *StubAPI) RemoveSubnet(subnetCIDR names.SubnetTag) error { 234 sa.MethodCall(sa, "RemoveSubnet", subnetCIDR) 235 return sa.NextErr() 236 } 237 238 func (sa *StubAPI) ListSubnets(withSpace *names.SpaceTag, withZone string) ([]params.Subnet, error) { 239 if withSpace == nil { 240 // Due to the way CheckCall works (using jc.DeepEquals 241 // internally), we need to pass an explicit nil here, rather 242 // than a pointer to a names.SpaceTag pointing to nil. 243 sa.MethodCall(sa, "ListSubnets", nil, withZone) 244 } else { 245 sa.MethodCall(sa, "ListSubnets", withSpace, withZone) 246 } 247 if err := sa.NextErr(); err != nil { 248 return nil, err 249 } 250 return sa.Subnets, nil 251 }