github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/storage/poollist_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage_test 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "fmt" 10 11 "github.com/juju/cmd" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 goyaml "gopkg.in/yaml.v2" 15 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/cmd/juju/storage" 18 _ "github.com/juju/juju/provider/dummy" 19 "github.com/juju/juju/testing" 20 ) 21 22 type poolListSuite struct { 23 SubStorageSuite 24 mockAPI *mockPoolListAPI 25 } 26 27 var _ = gc.Suite(&poolListSuite{}) 28 29 func (s *poolListSuite) SetUpTest(c *gc.C) { 30 s.SubStorageSuite.SetUpTest(c) 31 32 s.mockAPI = &mockPoolListAPI{ 33 attrs: map[string]interface{}{"key": "value", "one": "1", "two": 2}, 34 } 35 } 36 37 func (s *poolListSuite) runPoolList(c *gc.C, args []string) (*cmd.Context, error) { 38 args = append(args, []string{"-m", "admin"}...) 39 return testing.RunCommand(c, storage.NewPoolListCommandForTest(s.mockAPI, s.store), args...) 40 } 41 42 func (s *poolListSuite) TestPoolListEmpty(c *gc.C) { 43 // Both arguments - names and provider types - are optional. 44 // When none are supplied, all registered pools are listed. 45 // As this test uses mock api, no pools are registered by default. 46 // Returned list should be empty. 47 s.assertValidList( 48 c, 49 []string{""}, 50 "", 51 ) 52 } 53 54 const ( 55 providerA = "a" 56 providerB = "b" 57 58 nameABC = "abc" 59 nameXYZ = "xyz" 60 ) 61 62 func (s *poolListSuite) TestPoolListYAML(c *gc.C) { 63 s.assertUnmarshalledOutput(c, goyaml.Unmarshal, 64 "--provider", providerA, 65 "--provider", providerB, 66 "--name", nameABC, 67 "--name", nameXYZ, 68 "--format", "yaml") 69 } 70 71 func (s *poolListSuite) TestPoolListJSON(c *gc.C) { 72 s.assertUnmarshalledOutput(c, json.Unmarshal, 73 "--provider", providerA, 74 "--provider", providerB, 75 "--name", nameABC, 76 "--name", nameXYZ, 77 "--format", "json") 78 } 79 80 func (s *poolListSuite) TestPoolListTabular(c *gc.C) { 81 s.assertValidList( 82 c, 83 []string{"--provider", "a", "--provider", "b", 84 "--name", "xyz", "--name", "abc", 85 "--format", "tabular"}, 86 ` 87 NAME PROVIDER ATTRS 88 abc testType key=value one=1 two=2 89 testName0 a key=value one=1 two=2 90 testName1 b key=value one=1 two=2 91 xyz testType key=value one=1 two=2 92 93 `[1:]) 94 } 95 96 func (s *poolListSuite) TestPoolListTabularSortedWithAttrs(c *gc.C) { 97 s.mockAPI.attrs = map[string]interface{}{ 98 "a": true, "c": "well", "b": "maybe"} 99 100 s.assertValidList( 101 c, 102 []string{"--name", "myaw", "--name", "xyz", "--name", "abc", 103 "--format", "tabular"}, 104 ` 105 NAME PROVIDER ATTRS 106 abc testType a=true b=maybe c=well 107 myaw testType a=true b=maybe c=well 108 xyz testType a=true b=maybe c=well 109 110 `[1:]) 111 } 112 113 type unmarshaller func(in []byte, out interface{}) (err error) 114 115 func (s *poolListSuite) assertUnmarshalledOutput(c *gc.C, unmarshall unmarshaller, args ...string) { 116 117 context, err := s.runPoolList(c, args) 118 c.Assert(err, jc.ErrorIsNil) 119 var result map[string]storage.PoolInfo 120 err = unmarshall(context.Stdout.(*bytes.Buffer).Bytes(), &result) 121 c.Assert(err, jc.ErrorIsNil) 122 expected := s.expect(c, 123 []string{providerA, providerB}, 124 []string{nameABC, nameXYZ}) 125 // This comparison cannot rely on gc.DeepEquals as 126 // json.Unmarshal unmarshalls the number as a float64, 127 // rather than an int 128 s.assertSamePoolInfos(c, result, expected) 129 } 130 131 func (s poolListSuite) assertSamePoolInfos(c *gc.C, one, two map[string]storage.PoolInfo) { 132 c.Assert(one, gc.HasLen, len(two)) 133 134 sameAttributes := func(a, b map[string]interface{}) { 135 c.Assert(a, gc.HasLen, len(b)) 136 for ka, va := range a { 137 vb, okb := b[ka] 138 c.Assert(okb, jc.IsTrue) 139 // As some types may have been unmarshalled incorrectly, for example 140 // int versus float64, compare values' string representations 141 c.Assert(fmt.Sprintf("%v", va), jc.DeepEquals, fmt.Sprintf("%v", vb)) 142 } 143 } 144 145 for key, v1 := range one { 146 v2, ok := two[key] 147 c.Assert(ok, jc.IsTrue) 148 c.Assert(v1.Provider, gc.Equals, v2.Provider) 149 sameAttributes(v1.Attrs, v2.Attrs) 150 } 151 } 152 153 func (s poolListSuite) expect(c *gc.C, types, names []string) map[string]storage.PoolInfo { 154 all, err := s.mockAPI.ListPools(types, names) 155 c.Assert(err, jc.ErrorIsNil) 156 result := make(map[string]storage.PoolInfo, len(all)) 157 for _, one := range all { 158 result[one.Name] = storage.PoolInfo{one.Provider, one.Attrs} 159 } 160 return result 161 } 162 163 func (s *poolListSuite) assertValidList(c *gc.C, args []string, expected string) { 164 context, err := s.runPoolList(c, args) 165 c.Assert(err, jc.ErrorIsNil) 166 167 obtained := testing.Stdout(context) 168 c.Assert(obtained, gc.Equals, expected) 169 } 170 171 type mockPoolListAPI struct { 172 attrs map[string]interface{} 173 } 174 175 func (s mockPoolListAPI) Close() error { 176 return nil 177 } 178 179 func (s mockPoolListAPI) ListPools(types []string, names []string) ([]params.StoragePool, error) { 180 results := make([]params.StoragePool, len(types)+len(names)) 181 var index int 182 addInstance := func(aname, atype string) { 183 results[index] = s.createTestPoolInstance(aname, atype) 184 index++ 185 } 186 for i, atype := range types { 187 addInstance(fmt.Sprintf("testName%v", i), atype) 188 } 189 for _, aname := range names { 190 addInstance(aname, "testType") 191 } 192 return results, nil 193 } 194 195 func (s mockPoolListAPI) createTestPoolInstance(aname, atype string) params.StoragePool { 196 return params.StoragePool{ 197 Name: aname, 198 Provider: atype, 199 Attrs: s.attrs, 200 } 201 }