github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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 "strings" 8 stdtesting "testing" 9 10 "github.com/juju/cmd" 11 "github.com/juju/cmd/cmdtesting" 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/cmd/modelcmd" 20 "github.com/juju/juju/feature" 21 "github.com/juju/juju/jujuclient/jujuclienttesting" 22 coretesting "github.com/juju/juju/testing" 23 ) 24 25 func TestPackage(t *stdtesting.T) { 26 gc.TestingT(t) 27 } 28 29 // BaseSpaceSuite is used for embedding in other suites. 30 type BaseSpaceSuite struct { 31 coretesting.FakeJujuXDGDataHomeSuite 32 coretesting.BaseSuite 33 34 newCommand func() modelcmd.ModelCommand 35 api *StubAPI 36 } 37 38 var _ = gc.Suite(&BaseSpaceSuite{}) 39 40 func (s *BaseSpaceSuite) SetUpSuite(c *gc.C) { 41 s.FakeJujuXDGDataHomeSuite.SetUpSuite(c) 42 s.BaseSuite.SetUpSuite(c) 43 } 44 45 func (s *BaseSpaceSuite) TearDownSuite(c *gc.C) { 46 s.BaseSuite.TearDownSuite(c) 47 s.FakeJujuXDGDataHomeSuite.TearDownSuite(c) 48 } 49 50 func (s *BaseSpaceSuite) SetUpTest(c *gc.C) { 51 // If any post-MVP command suite enabled the flag, keep it. 52 hasFeatureFlag := featureflag.Enabled(feature.PostNetCLIMVP) 53 54 s.BaseSuite.SetUpTest(c) 55 s.FakeJujuXDGDataHomeSuite.SetUpTest(c) 56 57 if hasFeatureFlag { 58 s.BaseSuite.SetFeatureFlags(feature.PostNetCLIMVP) 59 } 60 61 s.api = NewStubAPI() 62 c.Assert(s.api, gc.NotNil) 63 64 // All subcommand suites embedding this one should initialize 65 // s.newCommand immediately after calling this method! 66 } 67 68 func (s *BaseSpaceSuite) TearDownTest(c *gc.C) { 69 s.FakeJujuXDGDataHomeSuite.TearDownTest(c) 70 s.BaseSuite.TearDownTest(c) 71 } 72 73 // InitCommand creates a command with s.newCommand and runs its 74 // Init method only. It returns the inner command and any error. 75 func (s *BaseSpaceSuite) InitCommand(c *gc.C, args ...string) (cmd.Command, error) { 76 cmd := s.newCommandForTest() 77 err := cmdtesting.InitCommand(cmd, args) 78 return modelcmd.InnerCommand(cmd), err 79 } 80 81 // RunCommand creates a command with s.newCommand and executes it, 82 // passing any args and returning the stdout and stderr output as 83 // strings, as well as any error. 84 func (s *BaseSpaceSuite) RunCommand(c *gc.C, args ...string) (string, string, error) { 85 cmd := s.newCommandForTest() 86 ctx, err := cmdtesting.RunCommand(c, cmd, args...) 87 return cmdtesting.Stdout(ctx), cmdtesting.Stderr(ctx), err 88 } 89 90 func (s *BaseSpaceSuite) newCommandForTest() modelcmd.ModelCommand { 91 cmd := s.newCommand() 92 // The client store shouldn't be used, but mock it 93 // out to make sure. 94 cmd.SetClientStore(jujuclienttesting.MinimalStore()) 95 cmd1 := modelcmd.InnerCommand(cmd).(interface { 96 SetAPI(space.SpaceAPI) 97 }) 98 cmd1.SetAPI(s.api) 99 return cmd 100 } 101 102 // AssertRunSpacesNotSupported is a shortcut for calling RunCommand with the 103 // passed args then asserting the output is empty and the error is the 104 // spaces not supported, finally returning the error. 105 func (s *BaseSpaceSuite) AssertRunSpacesNotSupported(c *gc.C, expectErr string, args ...string) error { 106 stdout, stderr, err := s.RunCommand(c, args...) 107 c.Assert(err, gc.ErrorMatches, expectErr) 108 c.Assert(stdout, gc.Equals, "") 109 c.Assert(stderr, gc.Equals, expectErr+"\n") 110 return err 111 } 112 113 // AssertRunFailsUnauthoirzed is a shortcut for calling RunCommand with the 114 // passed args then asserting the error is as expected, finally returning the 115 // error. 116 func (s *BaseSpaceSuite) AssertRunFailsUnauthorized(c *gc.C, expectErr string, args ...string) error { 117 _, stderr, err := s.RunCommand(c, args...) 118 c.Assert(strings.Replace(stderr, "\n", " ", -1), gc.Matches, `.*juju grant.*`) 119 return err 120 } 121 122 // AssertRunFails is a shortcut for calling RunCommand with the 123 // passed args then asserting the output is empty and the error is as 124 // expected, finally returning the error. 125 func (s *BaseSpaceSuite) AssertRunFails(c *gc.C, expectErr string, args ...string) error { 126 stdout, stderr, err := s.RunCommand(c, args...) 127 c.Assert(err, gc.ErrorMatches, expectErr) 128 c.Assert(stdout, gc.Equals, "") 129 c.Assert(stderr, gc.Equals, "") 130 return err 131 } 132 133 // AssertRunSucceeds is a shortcut for calling RunSuperCommand with 134 // the passed args then asserting the stderr output matches 135 // expectStderr, stdout is equal to expectStdout, and the error is 136 // nil. 137 func (s *BaseSpaceSuite) AssertRunSucceeds(c *gc.C, expectStderr, expectStdout string, args ...string) { 138 stdout, stderr, err := s.RunCommand(c, args...) 139 c.Assert(err, jc.ErrorIsNil) 140 c.Assert(stdout, gc.Equals, expectStdout) 141 c.Assert(stderr, gc.Matches, expectStderr) 142 } 143 144 // Strings is makes tests taking a slice of strings slightly easier to 145 // write: e.g. s.Strings("foo", "bar") vs. []string{"foo", "bar"}. 146 func (s *BaseSpaceSuite) Strings(values ...string) []string { 147 return values 148 } 149 150 // StubAPI defines a testing stub for the SpaceAPI interface. 151 type StubAPI struct { 152 *testing.Stub 153 154 Spaces []params.Space 155 Subnets []params.Subnet 156 } 157 158 var _ space.SpaceAPI = (*StubAPI)(nil) 159 160 // NewStubAPI creates a StubAPI suitable for passing to 161 // space.New*Command(). 162 func NewStubAPI() *StubAPI { 163 subnets := []params.Subnet{{ 164 // IPv6 subnet. 165 CIDR: "2001:db8::/32", 166 ProviderId: "subnet-public", 167 Life: params.Dying, 168 SpaceTag: "space-space1", 169 Zones: []string{"zone2"}, 170 }, { 171 // Invalid subnet (just for 100% coverage, otherwise it can't happen). 172 CIDR: "invalid", 173 ProviderId: "no-such", 174 SpaceTag: "space-space1", 175 Zones: []string{"zone1"}, 176 }, { 177 // IPv4 subnet. 178 CIDR: "10.1.2.0/24", 179 ProviderId: "subnet-private", 180 Life: params.Alive, 181 SpaceTag: "space-space2", 182 Zones: []string{"zone1", "zone2"}, 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 }} 192 spaces := []params.Space{{ 193 Name: "space1", 194 Subnets: append([]params.Subnet{}, subnets[:2]...), 195 }, { 196 Name: "space2", 197 Subnets: append([]params.Subnet{}, subnets[2:]...), 198 }} 199 return &StubAPI{ 200 Stub: &testing.Stub{}, 201 Spaces: spaces, 202 Subnets: subnets, 203 } 204 } 205 206 func (sa *StubAPI) Close() error { 207 sa.MethodCall(sa, "Close") 208 return sa.NextErr() 209 } 210 211 func (sa *StubAPI) ListSpaces() ([]params.Space, error) { 212 sa.MethodCall(sa, "ListSpaces") 213 if err := sa.NextErr(); err != nil { 214 return nil, err 215 } 216 return sa.Spaces, nil 217 } 218 219 func (sa *StubAPI) AddSpace(name string, subnetIds []string, public bool) error { 220 sa.MethodCall(sa, "AddSpace", name, subnetIds, public) 221 return sa.NextErr() 222 } 223 224 func (sa *StubAPI) RemoveSpace(name string) error { 225 sa.MethodCall(sa, "RemoveSpace", name) 226 return sa.NextErr() 227 } 228 229 func (sa *StubAPI) UpdateSpace(name string, subnetIds []string) error { 230 sa.MethodCall(sa, "UpdateSpace", name, subnetIds) 231 return sa.NextErr() 232 } 233 234 func (sa *StubAPI) RenameSpace(name, newName string) error { 235 sa.MethodCall(sa, "RenameSpace", name, newName) 236 return sa.NextErr() 237 } 238 239 func (sa *StubAPI) ReloadSpaces() error { 240 sa.MethodCall(sa, "ReloadSpaces") 241 return sa.NextErr() 242 }