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  }