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