github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/space/list_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  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"regexp"
    13  
    14  	"github.com/juju/errors"
    15  	jc "github.com/juju/testing/checkers"
    16  	gc "gopkg.in/check.v1"
    17  
    18  	"github.com/juju/juju/cmd/juju/space"
    19  	coretesting "github.com/juju/juju/testing"
    20  )
    21  
    22  type ListSuite struct {
    23  	BaseSpaceSuite
    24  }
    25  
    26  var _ = gc.Suite(&ListSuite{})
    27  
    28  func (s *ListSuite) SetUpTest(c *gc.C) {
    29  	s.BaseSpaceSuite.SetUpTest(c)
    30  	s.command, _ = space.NewListCommandForTest(s.api)
    31  	c.Assert(s.command, gc.NotNil)
    32  }
    33  
    34  func (s *ListSuite) TestInit(c *gc.C) {
    35  	for i, test := range []struct {
    36  		about        string
    37  		args         []string
    38  		expectShort  bool
    39  		expectFormat string
    40  		expectErr    string
    41  	}{{
    42  		about:        "unrecognized arguments",
    43  		args:         s.Strings("foo"),
    44  		expectErr:    `unrecognized args: \["foo"\]`,
    45  		expectFormat: "tabular",
    46  	}, {
    47  		about:        "invalid format",
    48  		args:         s.Strings("--format", "foo"),
    49  		expectErr:    `invalid value "foo" for flag --format: unknown format "foo"`,
    50  		expectFormat: "tabular",
    51  	}, {
    52  		about:        "invalid format (value is case-sensitive)",
    53  		args:         s.Strings("--format", "JSON"),
    54  		expectErr:    `invalid value "JSON" for flag --format: unknown format "JSON"`,
    55  		expectFormat: "tabular",
    56  	}, {
    57  		about:        "json format",
    58  		args:         s.Strings("--format", "json"),
    59  		expectFormat: "json",
    60  	}, {
    61  		about:        "yaml format",
    62  		args:         s.Strings("--format", "yaml"),
    63  		expectFormat: "yaml",
    64  	}, {
    65  		about:        "tabular format",
    66  		args:         s.Strings("--format", "tabular"),
    67  		expectFormat: "tabular",
    68  	}, {
    69  		// --output and -o are tested separately in TestOutputFormats.
    70  		about:        "both --output and -o specified (latter overrides former)",
    71  		args:         s.Strings("--output", "foo", "-o", "bar"),
    72  		expectFormat: "tabular",
    73  	}} {
    74  		c.Logf("test #%d: %s", i, test.about)
    75  		// Create a new instance of the subcommand for each test, but
    76  		// since we're not running the command no need to use
    77  		// modelcmd.Wrap().
    78  		wrappedCommand, command := space.NewListCommandForTest(s.api)
    79  		err := coretesting.InitCommand(wrappedCommand, test.args)
    80  		if test.expectErr != "" {
    81  			c.Check(err, gc.ErrorMatches, test.expectErr)
    82  		} else {
    83  			c.Check(err, jc.ErrorIsNil)
    84  		}
    85  		c.Check(command.ListFormat(), gc.Equals, test.expectFormat)
    86  		c.Check(command.Short, gc.Equals, test.expectShort)
    87  
    88  		// No API calls should be recorded at this stage.
    89  		s.api.CheckCallNames(c)
    90  	}
    91  }
    92  
    93  func (s *ListSuite) TestOutputFormats(c *gc.C) {
    94  	outDir := c.MkDir()
    95  	expectedYAML := `
    96  spaces:
    97    space1:
    98      2001:db8::/32:
    99        type: ipv6
   100        provider-id: subnet-public
   101        status: terminating
   102        zones:
   103        - zone2
   104      invalid:
   105        type: unknown
   106        provider-id: no-such
   107        status: 'error: invalid subnet CIDR: invalid'
   108        zones:
   109        - zone1
   110    space2:
   111      4.3.2.0/28:
   112        type: ipv4
   113        provider-id: vlan-42
   114        status: terminating
   115        zones:
   116        - zone1
   117      10.1.2.0/24:
   118        type: ipv4
   119        provider-id: subnet-private
   120        status: in-use
   121        zones:
   122        - zone1
   123        - zone2
   124  `[1:]
   125  	unwrap := regexp.MustCompile(`[\s+\n]`)
   126  	expectedJSON := unwrap.ReplaceAllLiteralString(`
   127  {
   128    "spaces": {
   129      "space1": {
   130        "2001:db8::/32": {
   131          "type": "ipv6",
   132          "provider-id": "subnet-public",
   133          "status": "terminating",
   134          "zones": ["zone2"]
   135        },
   136        "invalid": {
   137          "type": "unknown",
   138          "provider-id": "no-such",
   139          "status": "error: invalid subnet CIDR: invalid",
   140          "zones": ["zone1"]
   141        }
   142      },
   143      "space2": {
   144        "10.1.2.0/24": {
   145          "type": "ipv4",
   146          "provider-id": "subnet-private",
   147          "status": "in-use",
   148          "zones": ["zone1","zone2"]
   149        },
   150        "4.3.2.0/28": {
   151          "type": "ipv4",
   152          "provider-id": "vlan-42",
   153          "status": "terminating",
   154          "zones": ["zone1"]
   155        }
   156      }
   157    }
   158  }
   159  `, "") + "\n"
   160  	// Work around the big unwrap hammer above.
   161  	expectedJSON = strings.Replace(
   162  		expectedJSON,
   163  		"error:invalidsubnetCIDR:invalid",
   164  		"error: invalid subnet CIDR: invalid",
   165  		1,
   166  	)
   167  	expectedShortYAML := `
   168  spaces:
   169  - space1
   170  - space2
   171  `[1:]
   172  
   173  	expectedShortJSON := unwrap.ReplaceAllLiteralString(`
   174  {
   175    "spaces": [
   176      "space1",
   177      "space2"
   178    ]
   179  }
   180  `, "") + "\n"
   181  
   182  	expectedTabular := `SPACE   SUBNETS
   183  space1  2001:db8::/32
   184          invalid
   185  space2  10.1.2.0/24
   186          4.3.2.0/28
   187  
   188  `
   189  	expectedShortTabular := `SPACE
   190  space1
   191  space2
   192  
   193  `
   194  
   195  	assertAPICalls := func() {
   196  		// Verify the API calls and reset the recorded calls.
   197  		s.api.CheckCallNames(c, "ListSpaces", "Close")
   198  		s.api.ResetCalls()
   199  	}
   200  	makeArgs := func(format string, short bool, extraArgs ...string) []string {
   201  		args := s.Strings(extraArgs...)
   202  		if format != "" {
   203  			args = append(args, "--format", format)
   204  		}
   205  		if short == true {
   206  			args = append(args, "--short")
   207  		}
   208  		return args
   209  	}
   210  	assertOutput := func(format, expected string, short bool) {
   211  		outFile := filepath.Join(outDir, "output")
   212  		c.Assert(outFile, jc.DoesNotExist)
   213  		defer os.Remove(outFile)
   214  		// Check -o works.
   215  		var args []string
   216  		args = makeArgs(format, short, "-o", outFile)
   217  		s.AssertRunSucceeds(c, "", "", args...)
   218  		assertAPICalls()
   219  
   220  		data, err := ioutil.ReadFile(outFile)
   221  		c.Assert(err, jc.ErrorIsNil)
   222  		c.Assert(string(data), gc.Equals, expected)
   223  
   224  		// Check the last output argument takes precedence when both
   225  		// -o and --output are given (and also that --output works the
   226  		// same as -o).
   227  		outFile1 := filepath.Join(outDir, "output1")
   228  		c.Assert(outFile1, jc.DoesNotExist)
   229  		defer os.Remove(outFile1)
   230  		outFile2 := filepath.Join(outDir, "output2")
   231  		c.Assert(outFile2, jc.DoesNotExist)
   232  		defer os.Remove(outFile2)
   233  		// Write something in outFile2 to verify its contents are
   234  		// overwritten.
   235  		err = ioutil.WriteFile(outFile2, []byte("some contents"), 0644)
   236  		c.Assert(err, jc.ErrorIsNil)
   237  
   238  		args = makeArgs(format, short, "-o", outFile1, "--output", outFile2)
   239  		s.AssertRunSucceeds(c, "", "", args...)
   240  		// Check only the last output file was used, and the output
   241  		// file was overwritten.
   242  		c.Assert(outFile1, jc.DoesNotExist)
   243  		data, err = ioutil.ReadFile(outFile2)
   244  		c.Assert(err, jc.ErrorIsNil)
   245  		c.Assert(string(data), gc.Equals, expected)
   246  		assertAPICalls()
   247  
   248  		// Finally, check without --output.
   249  		args = makeArgs(format, short)
   250  		s.AssertRunSucceeds(c, "", expected, args...)
   251  		assertAPICalls()
   252  	}
   253  
   254  	for i, test := range []struct {
   255  		format   string
   256  		expected string
   257  		short    bool
   258  	}{
   259  		{"", expectedTabular, false}, // default format is tabular
   260  		{"tabular", expectedTabular, false},
   261  		{"yaml", expectedYAML, false},
   262  		{"json", expectedJSON, false},
   263  		{"", expectedShortTabular, true}, // default format is tabular
   264  		{"tabular", expectedShortTabular, true},
   265  		{"yaml", expectedShortYAML, true},
   266  		{"json", expectedShortJSON, true},
   267  	} {
   268  		c.Logf("test #%d: format %q, short %v", i, test.format, test.short)
   269  		assertOutput(test.format, test.expected, test.short)
   270  	}
   271  }
   272  
   273  func (s *ListSuite) TestRunWhenNoSpacesExistSucceeds(c *gc.C) {
   274  	s.api.Spaces = s.api.Spaces[0:0]
   275  
   276  	s.AssertRunSucceeds(c,
   277  		`no spaces to display\n`,
   278  		"", // empty stdout.
   279  	)
   280  
   281  	s.api.CheckCallNames(c, "ListSpaces", "Close")
   282  	s.api.CheckCall(c, 0, "ListSpaces")
   283  }
   284  
   285  func (s *ListSuite) TestRunWhenSpacesNotSupported(c *gc.C) {
   286  	s.api.SetErrors(errors.NewNotSupported(nil, "spaces not supported"))
   287  
   288  	err := s.AssertRunSpacesNotSupported(c, "cannot list spaces: spaces not supported")
   289  	c.Assert(err, jc.Satisfies, errors.IsNotSupported)
   290  
   291  	s.api.CheckCallNames(c, "ListSpaces", "Close")
   292  	s.api.CheckCall(c, 0, "ListSpaces")
   293  }
   294  
   295  func (s *ListSuite) TestRunWhenSpacesAPIFails(c *gc.C) {
   296  	s.api.SetErrors(errors.New("boom"))
   297  
   298  	s.AssertRunFails(c, "cannot list spaces: boom")
   299  
   300  	s.api.CheckCallNames(c, "ListSpaces", "Close")
   301  	s.api.CheckCall(c, 0, "ListSpaces")
   302  }