github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap/cmd_interfaces_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package main_test
    21  
    22  import (
    23  	"io/ioutil"
    24  	"net/http"
    25  	"os"
    26  
    27  	"github.com/jessevdk/go-flags"
    28  	. "gopkg.in/check.v1"
    29  
    30  	"github.com/snapcore/snapd/client"
    31  	. "github.com/snapcore/snapd/cmd/snap"
    32  	"github.com/snapcore/snapd/testutil"
    33  )
    34  
    35  func (s *SnapSuite) TestInterfacesZeroSlotsOnePlug(c *C) {
    36  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
    37  		c.Check(r.Method, Equals, "GET")
    38  		c.Check(r.URL.Path, Equals, "/v2/connections")
    39  		body, err := ioutil.ReadAll(r.Body)
    40  		c.Check(err, IsNil)
    41  		c.Check(body, DeepEquals, []byte{})
    42  		EncodeResponseBody(c, w, map[string]interface{}{
    43  			"type": "sync",
    44  			"result": client.Connections{
    45  				Plugs: []client.Plug{
    46  					{
    47  						Snap: "keyboard-lights",
    48  						Name: "capslock-led",
    49  					},
    50  				},
    51  			},
    52  		})
    53  	})
    54  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
    55  	c.Assert(err, IsNil)
    56  	c.Assert(rest, DeepEquals, []string{})
    57  	expectedStdout := "" +
    58  		"Slot  Plug\n" +
    59  		"-     keyboard-lights:capslock-led\n"
    60  	c.Assert(s.Stdout(), Equals, expectedStdout)
    61  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
    62  }
    63  
    64  func (s *SnapSuite) TestInterfacesZeroPlugsOneSlot(c *C) {
    65  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
    66  		c.Check(r.Method, Equals, "GET")
    67  		c.Check(r.URL.Path, Equals, "/v2/connections")
    68  		body, err := ioutil.ReadAll(r.Body)
    69  		c.Check(err, IsNil)
    70  		c.Check(body, DeepEquals, []byte{})
    71  		EncodeResponseBody(c, w, map[string]interface{}{
    72  			"type": "sync",
    73  			"result": client.Connections{
    74  				Slots: []client.Slot{
    75  					{
    76  						Snap:      "canonical-pi2",
    77  						Name:      "pin-13",
    78  						Interface: "bool-file",
    79  						Label:     "Pin 13",
    80  					},
    81  				},
    82  			},
    83  		})
    84  	})
    85  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
    86  	c.Assert(err, IsNil)
    87  	c.Assert(rest, DeepEquals, []string{})
    88  	expectedStdout := "" +
    89  		"Slot                  Plug\n" +
    90  		"canonical-pi2:pin-13  -\n"
    91  	c.Assert(s.Stdout(), Equals, expectedStdout)
    92  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
    93  }
    94  
    95  func (s *SnapSuite) TestInterfacesOneSlotOnePlug(c *C) {
    96  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
    97  		c.Check(r.Method, Equals, "GET")
    98  		c.Check(r.URL.Path, Equals, "/v2/connections")
    99  		body, err := ioutil.ReadAll(r.Body)
   100  		c.Check(err, IsNil)
   101  		c.Check(body, DeepEquals, []byte{})
   102  		EncodeResponseBody(c, w, map[string]interface{}{
   103  			"type": "sync",
   104  			"result": client.Connections{
   105  				Slots: []client.Slot{
   106  					{
   107  						Snap:      "canonical-pi2",
   108  						Name:      "pin-13",
   109  						Interface: "bool-file",
   110  						Label:     "Pin 13",
   111  						Connections: []client.PlugRef{
   112  							{
   113  								Snap: "keyboard-lights",
   114  								Name: "capslock-led",
   115  							},
   116  						},
   117  					},
   118  				},
   119  				Plugs: []client.Plug{
   120  					{
   121  						Snap:      "keyboard-lights",
   122  						Name:      "capslock-led",
   123  						Interface: "bool-file",
   124  						Label:     "Capslock indicator LED",
   125  						Connections: []client.SlotRef{
   126  							{
   127  								Snap: "canonical-pi2",
   128  								Name: "pin-13",
   129  							},
   130  						},
   131  					},
   132  				},
   133  			},
   134  		})
   135  	})
   136  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
   137  	c.Assert(err, IsNil)
   138  	c.Assert(rest, DeepEquals, []string{})
   139  	expectedStdout := "" +
   140  		"Slot                  Plug\n" +
   141  		"canonical-pi2:pin-13  keyboard-lights:capslock-led\n"
   142  	c.Assert(s.Stdout(), Equals, expectedStdout)
   143  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   144  
   145  	s.ResetStdStreams()
   146  	// should be the same
   147  	rest, err = Parser(Client()).ParseArgs([]string{"interfaces", "canonical-pi2"})
   148  	c.Assert(err, IsNil)
   149  	c.Assert(rest, DeepEquals, []string{})
   150  	c.Assert(s.Stdout(), Equals, expectedStdout)
   151  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   152  	s.ResetStdStreams()
   153  	// and the same again
   154  	rest, err = Parser(Client()).ParseArgs([]string{"interfaces", "keyboard-lights"})
   155  	c.Assert(err, IsNil)
   156  	c.Assert(rest, DeepEquals, []string{})
   157  	c.Assert(s.Stdout(), Equals, expectedStdout)
   158  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   159  }
   160  
   161  func (s *SnapSuite) TestInterfacesTwoPlugs(c *C) {
   162  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   163  		c.Check(r.Method, Equals, "GET")
   164  		c.Check(r.URL.Path, Equals, "/v2/connections")
   165  		body, err := ioutil.ReadAll(r.Body)
   166  		c.Check(err, IsNil)
   167  		c.Check(body, DeepEquals, []byte{})
   168  		EncodeResponseBody(c, w, map[string]interface{}{
   169  			"type": "sync",
   170  			"result": client.Connections{
   171  				Slots: []client.Slot{
   172  					{
   173  						Snap:      "canonical-pi2",
   174  						Name:      "pin-13",
   175  						Interface: "bool-file",
   176  						Label:     "Pin 13",
   177  						Connections: []client.PlugRef{
   178  							{
   179  								Snap: "keyboard-lights",
   180  								Name: "capslock-led",
   181  							},
   182  							{
   183  								Snap: "keyboard-lights",
   184  								Name: "scrollock-led",
   185  							},
   186  						},
   187  					},
   188  				},
   189  			},
   190  		})
   191  	})
   192  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
   193  	c.Assert(err, IsNil)
   194  	c.Assert(rest, DeepEquals, []string{})
   195  	expectedStdout := "" +
   196  		"Slot                  Plug\n" +
   197  		"canonical-pi2:pin-13  keyboard-lights:capslock-led,keyboard-lights:scrollock-led\n"
   198  	c.Assert(s.Stdout(), Equals, expectedStdout)
   199  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   200  }
   201  
   202  func (s *SnapSuite) TestInterfacesPlugsWithCommonName(c *C) {
   203  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   204  		c.Check(r.Method, Equals, "GET")
   205  		c.Check(r.URL.Path, Equals, "/v2/connections")
   206  		body, err := ioutil.ReadAll(r.Body)
   207  		c.Check(err, IsNil)
   208  		c.Check(body, DeepEquals, []byte{})
   209  		EncodeResponseBody(c, w, map[string]interface{}{
   210  			"type": "sync",
   211  			"result": client.Connections{
   212  				Slots: []client.Slot{
   213  					{
   214  						Snap:      "canonical-pi2",
   215  						Name:      "network-listening",
   216  						Interface: "network-listening",
   217  						Label:     "Ability to be a network service",
   218  						Connections: []client.PlugRef{
   219  							{
   220  								Snap: "paste-daemon",
   221  								Name: "network-listening",
   222  							},
   223  							{
   224  								Snap: "time-daemon",
   225  								Name: "network-listening",
   226  							},
   227  						},
   228  					},
   229  				},
   230  				Plugs: []client.Plug{
   231  					{
   232  						Snap:      "paste-daemon",
   233  						Name:      "network-listening",
   234  						Interface: "network-listening",
   235  						Label:     "Ability to be a network service",
   236  						Connections: []client.SlotRef{
   237  							{
   238  								Snap: "canonical-pi2",
   239  								Name: "network-listening",
   240  							},
   241  						},
   242  					},
   243  					{
   244  						Snap:      "time-daemon",
   245  						Name:      "network-listening",
   246  						Interface: "network-listening",
   247  						Label:     "Ability to be a network service",
   248  						Connections: []client.SlotRef{
   249  							{
   250  								Snap: "canonical-pi2",
   251  								Name: "network-listening",
   252  							},
   253  						},
   254  					},
   255  				},
   256  			},
   257  		})
   258  	})
   259  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
   260  	c.Assert(err, IsNil)
   261  	c.Assert(rest, DeepEquals, []string{})
   262  	expectedStdout := "" +
   263  		"Slot                             Plug\n" +
   264  		"canonical-pi2:network-listening  paste-daemon,time-daemon\n"
   265  	c.Assert(s.Stdout(), Equals, expectedStdout)
   266  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   267  }
   268  
   269  func (s *SnapSuite) TestInterfacesOsSnapSlots(c *C) {
   270  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   271  		c.Check(r.Method, Equals, "GET")
   272  		c.Check(r.URL.Path, Equals, "/v2/connections")
   273  		body, err := ioutil.ReadAll(r.Body)
   274  		c.Check(err, IsNil)
   275  		c.Check(body, DeepEquals, []byte{})
   276  		EncodeResponseBody(c, w, map[string]interface{}{
   277  			"type": "sync",
   278  			"result": client.Connections{
   279  				Slots: []client.Slot{
   280  					{
   281  						Snap:      "system",
   282  						Name:      "network-listening",
   283  						Interface: "network-listening",
   284  						Label:     "Ability to be a network service",
   285  						Connections: []client.PlugRef{
   286  							{
   287  								Snap: "paste-daemon",
   288  								Name: "network-listening",
   289  							},
   290  							{
   291  								Snap: "time-daemon",
   292  								Name: "network-listening",
   293  							},
   294  						},
   295  					},
   296  				},
   297  				Plugs: []client.Plug{
   298  					{
   299  						Snap:      "paste-daemon",
   300  						Name:      "network-listening",
   301  						Interface: "network-listening",
   302  						Label:     "Ability to be a network service",
   303  						Connections: []client.SlotRef{
   304  							{
   305  								Snap: "system",
   306  								Name: "network-listening",
   307  							},
   308  						},
   309  					},
   310  					{
   311  						Snap:      "time-daemon",
   312  						Name:      "network-listening",
   313  						Interface: "network-listening",
   314  						Label:     "Ability to be a network service",
   315  						Connections: []client.SlotRef{
   316  							{
   317  								Snap: "system",
   318  								Name: "network-listening",
   319  							},
   320  						},
   321  					},
   322  				},
   323  			},
   324  		})
   325  	})
   326  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
   327  	c.Assert(err, IsNil)
   328  	c.Assert(rest, DeepEquals, []string{})
   329  	expectedStdout := "" +
   330  		"Slot                Plug\n" +
   331  		":network-listening  paste-daemon,time-daemon\n"
   332  	c.Assert(s.Stdout(), Equals, expectedStdout)
   333  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   334  }
   335  
   336  func (s *SnapSuite) TestInterfacesTwoSlotsAndFiltering(c *C) {
   337  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   338  		c.Check(r.Method, Equals, "GET")
   339  		c.Check(r.URL.Path, Equals, "/v2/connections")
   340  		body, err := ioutil.ReadAll(r.Body)
   341  		c.Check(err, IsNil)
   342  		c.Check(body, DeepEquals, []byte{})
   343  		EncodeResponseBody(c, w, map[string]interface{}{
   344  			"type": "sync",
   345  			"result": client.Connections{
   346  				Slots: []client.Slot{
   347  					{
   348  						Snap:      "canonical-pi2",
   349  						Name:      "debug-console",
   350  						Interface: "serial-port",
   351  						Label:     "Serial port on the expansion header",
   352  						Connections: []client.PlugRef{
   353  							{
   354  								Snap: "core",
   355  								Name: "debug-console",
   356  							},
   357  						},
   358  					},
   359  					{
   360  						Snap:      "canonical-pi2",
   361  						Name:      "pin-13",
   362  						Interface: "bool-file",
   363  						Label:     "Pin 13",
   364  						Connections: []client.PlugRef{
   365  							{
   366  								Snap: "keyboard-lights",
   367  								Name: "capslock-led",
   368  							},
   369  						},
   370  					},
   371  				},
   372  			},
   373  		})
   374  	})
   375  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces", "-i=serial-port"})
   376  	c.Assert(err, IsNil)
   377  	c.Assert(rest, DeepEquals, []string{})
   378  	expectedStdout := "" +
   379  		"Slot                         Plug\n" +
   380  		"canonical-pi2:debug-console  core\n"
   381  	c.Assert(s.Stdout(), Equals, expectedStdout)
   382  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   383  }
   384  
   385  func (s *SnapSuite) TestInterfacesOfSpecificSnap(c *C) {
   386  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   387  		c.Check(r.Method, Equals, "GET")
   388  		c.Check(r.URL.Path, Equals, "/v2/connections")
   389  		body, err := ioutil.ReadAll(r.Body)
   390  		c.Check(err, IsNil)
   391  		c.Check(body, DeepEquals, []byte{})
   392  		EncodeResponseBody(c, w, map[string]interface{}{
   393  			"type": "sync",
   394  			"result": client.Connections{
   395  				Slots: []client.Slot{
   396  					{
   397  						Snap:      "cheese",
   398  						Name:      "photo-trigger",
   399  						Interface: "bool-file",
   400  						Label:     "Photo trigger",
   401  					},
   402  					{
   403  						Snap:      "wake-up-alarm",
   404  						Name:      "toggle",
   405  						Interface: "bool-file",
   406  						Label:     "Alarm toggle",
   407  					},
   408  					{
   409  						Snap:      "wake-up-alarm",
   410  						Name:      "snooze",
   411  						Interface: "bool-file",
   412  						Label:     "Alarm snooze",
   413  					},
   414  				},
   415  			},
   416  		})
   417  	})
   418  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces", "wake-up-alarm"})
   419  	c.Assert(err, IsNil)
   420  	c.Assert(rest, DeepEquals, []string{})
   421  	expectedStdout := "" +
   422  		"Slot                  Plug\n" +
   423  		"wake-up-alarm:toggle  -\n" +
   424  		"wake-up-alarm:snooze  -\n"
   425  	c.Assert(s.Stdout(), Equals, expectedStdout)
   426  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   427  }
   428  
   429  func (s *SnapSuite) TestInterfacesOfSystemNicknameSnap(c *C) {
   430  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   431  		c.Check(r.Method, Equals, "GET")
   432  		c.Check(r.URL.Path, Equals, "/v2/connections")
   433  		body, err := ioutil.ReadAll(r.Body)
   434  		c.Check(err, IsNil)
   435  		c.Check(body, DeepEquals, []byte{})
   436  		EncodeResponseBody(c, w, map[string]interface{}{
   437  			"type": "sync",
   438  			"result": client.Connections{
   439  				Slots: []client.Slot{
   440  					{
   441  						Snap:        "system",
   442  						Name:        "core-support",
   443  						Interface:   "some-iface",
   444  						Connections: []client.PlugRef{{Snap: "core", Name: "core-support-plug"}},
   445  					}, {
   446  						Snap:      "foo",
   447  						Name:      "foo-slot",
   448  						Interface: "foo-slot-iface",
   449  					},
   450  				},
   451  				Plugs: []client.Plug{
   452  					{
   453  						Snap:        "core",
   454  						Name:        "core-support-plug",
   455  						Interface:   "some-iface",
   456  						Connections: []client.SlotRef{{Snap: "system", Name: "core-support"}},
   457  					},
   458  				},
   459  			},
   460  		})
   461  	})
   462  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces", "system"})
   463  	c.Assert(err, IsNil)
   464  	c.Assert(rest, DeepEquals, []string{})
   465  	expectedStdout := "" +
   466  		"Slot           Plug\n" +
   467  		":core-support  core:core-support-plug\n"
   468  	c.Assert(s.Stdout(), Equals, expectedStdout)
   469  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   470  
   471  	s.ResetStdStreams()
   472  
   473  	// when called with system nickname we get the same output
   474  	rest, err = Parser(Client()).ParseArgs([]string{"interfaces", "system"})
   475  	c.Assert(err, IsNil)
   476  	c.Assert(rest, DeepEquals, []string{})
   477  	expectedStdoutSystem := "" +
   478  		"Slot           Plug\n" +
   479  		":core-support  core:core-support-plug\n"
   480  	c.Assert(s.Stdout(), Equals, expectedStdoutSystem)
   481  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   482  }
   483  
   484  func (s *SnapSuite) TestInterfacesOfSpecificSnapAndSlot(c *C) {
   485  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   486  		c.Check(r.Method, Equals, "GET")
   487  		c.Check(r.URL.Path, Equals, "/v2/connections")
   488  		body, err := ioutil.ReadAll(r.Body)
   489  		c.Check(err, IsNil)
   490  		c.Check(body, DeepEquals, []byte{})
   491  		EncodeResponseBody(c, w, map[string]interface{}{
   492  			"type": "sync",
   493  			"result": client.Connections{
   494  				Slots: []client.Slot{
   495  					{
   496  						Snap:      "cheese",
   497  						Name:      "photo-trigger",
   498  						Interface: "bool-file",
   499  						Label:     "Photo trigger",
   500  					},
   501  					{
   502  						Snap:      "wake-up-alarm",
   503  						Name:      "toggle",
   504  						Interface: "bool-file",
   505  						Label:     "Alarm toggle",
   506  					},
   507  					{
   508  						Snap:      "wake-up-alarm",
   509  						Name:      "snooze",
   510  						Interface: "bool-file",
   511  						Label:     "Alarm snooze",
   512  					},
   513  				},
   514  			},
   515  		})
   516  	})
   517  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces", "wake-up-alarm:snooze"})
   518  	c.Assert(err, IsNil)
   519  	c.Assert(rest, DeepEquals, []string{})
   520  	expectedStdout := "" +
   521  		"Slot                  Plug\n" +
   522  		"wake-up-alarm:snooze  -\n"
   523  	c.Assert(s.Stdout(), Equals, expectedStdout)
   524  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   525  }
   526  
   527  func (s *SnapSuite) TestInterfacesNothingAtAll(c *C) {
   528  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   529  		c.Check(r.Method, Equals, "GET")
   530  		c.Check(r.URL.Path, Equals, "/v2/connections")
   531  		body, err := ioutil.ReadAll(r.Body)
   532  		c.Check(err, IsNil)
   533  		c.Check(body, DeepEquals, []byte{})
   534  		EncodeResponseBody(c, w, map[string]interface{}{
   535  			"type":   "sync",
   536  			"result": client.Connections{},
   537  		})
   538  	})
   539  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces"})
   540  	c.Assert(err, ErrorMatches, "no interfaces found")
   541  	// XXX: not sure why this is returned, I guess that's what happens when a
   542  	// command Execute returns an error.
   543  	c.Assert(rest, DeepEquals, []string{"interfaces"})
   544  	c.Assert(s.Stdout(), Equals, "")
   545  	c.Assert(s.Stderr(), Equals, "")
   546  }
   547  
   548  func (s *SnapSuite) TestInterfacesOfSpecificType(c *C) {
   549  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   550  		c.Check(r.Method, Equals, "GET")
   551  		c.Check(r.URL.Path, Equals, "/v2/connections")
   552  		body, err := ioutil.ReadAll(r.Body)
   553  		c.Check(err, IsNil)
   554  		c.Check(body, DeepEquals, []byte{})
   555  		EncodeResponseBody(c, w, map[string]interface{}{
   556  			"type": "sync",
   557  			"result": client.Connections{
   558  				Slots: []client.Slot{
   559  					{
   560  						Snap:      "cheese",
   561  						Name:      "photo-trigger",
   562  						Interface: "bool-file",
   563  						Label:     "Photo trigger",
   564  					},
   565  					{
   566  						Snap:      "wake-up-alarm",
   567  						Name:      "toggle",
   568  						Interface: "bool-file",
   569  						Label:     "Alarm toggle",
   570  					},
   571  					{
   572  						Snap:      "wake-up-alarm",
   573  						Name:      "snooze",
   574  						Interface: "bool-file",
   575  						Label:     "Alarm snooze",
   576  					},
   577  				},
   578  			},
   579  		})
   580  	})
   581  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces", "-i", "bool-file"})
   582  	c.Assert(err, IsNil)
   583  	c.Assert(rest, DeepEquals, []string{})
   584  	expectedStdout := "" +
   585  		"Slot                  Plug\n" +
   586  		"cheese:photo-trigger  -\n" +
   587  		"wake-up-alarm:toggle  -\n" +
   588  		"wake-up-alarm:snooze  -\n"
   589  	c.Assert(s.Stdout(), Equals, expectedStdout)
   590  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   591  }
   592  
   593  func (s *SnapSuite) TestInterfacesCompletion(c *C) {
   594  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   595  		switch r.URL.Path {
   596  		case "/v2/connections":
   597  			c.Assert(r.Method, Equals, "GET")
   598  			EncodeResponseBody(c, w, map[string]interface{}{
   599  				"type":   "sync",
   600  				"result": fortestingConnectionList,
   601  			})
   602  		default:
   603  			c.Fatalf("unexpected path %q", r.URL.Path)
   604  		}
   605  	})
   606  	os.Setenv("GO_FLAGS_COMPLETION", "verbose")
   607  	defer os.Unsetenv("GO_FLAGS_COMPLETION")
   608  
   609  	expected := []flags.Completion{}
   610  	parser := Parser(Client())
   611  	parser.CompletionHandler = func(obtained []flags.Completion) {
   612  		c.Check(obtained, DeepEquals, expected)
   613  	}
   614  
   615  	expected = []flags.Completion{{Item: "canonical-pi2:"}, {Item: "core:"}, {Item: "keyboard-lights:"}, {Item: "paste-daemon:"}, {Item: "potato:"}, {Item: "wake-up-alarm:"}}
   616  	_, err := parser.ParseArgs([]string{"interfaces", ""})
   617  	c.Assert(err, IsNil)
   618  
   619  	expected = []flags.Completion{{Item: "paste-daemon:network-listening", Description: "plug"}}
   620  	_, err = parser.ParseArgs([]string{"interfaces", "pa"})
   621  	c.Assert(err, IsNil)
   622  
   623  	expected = []flags.Completion{{Item: "wake-up-alarm:toggle", Description: "slot"}}
   624  	_, err = parser.ParseArgs([]string{"interfaces", "wa"})
   625  	c.Assert(err, IsNil)
   626  
   627  	c.Assert(s.Stdout(), Equals, "")
   628  	c.Assert(s.Stderr(), Equals, "")
   629  }
   630  
   631  func (s *SnapSuite) TestInterfacesCoreNicknamedSystem(c *C) {
   632  	s.checkConnectionsSystemCoreRemapping(c, "core", "system")
   633  }
   634  
   635  func (s *SnapSuite) TestInterfacesSnapdNicknamedSystem(c *C) {
   636  	s.checkConnectionsSystemCoreRemapping(c, "snapd", "system")
   637  }
   638  
   639  func (s *SnapSuite) TestInterfacesSnapdNicknamedCore(c *C) {
   640  	s.checkConnectionsSystemCoreRemapping(c, "snapd", "core")
   641  }
   642  
   643  func (s *SnapSuite) TestInterfacesCoreSnap(c *C) {
   644  	s.checkConnectionsSystemCoreRemapping(c, "core", "core")
   645  }
   646  
   647  func (s *SnapSuite) checkConnectionsSystemCoreRemapping(c *C, apiSnapName, cliSnapName string) {
   648  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   649  		c.Check(r.Method, Equals, "GET")
   650  		c.Check(r.URL.Path, Equals, "/v2/connections")
   651  		body, err := ioutil.ReadAll(r.Body)
   652  		c.Check(err, IsNil)
   653  		c.Check(body, DeepEquals, []byte{})
   654  		EncodeResponseBody(c, w, map[string]interface{}{
   655  			"type": "sync",
   656  			"result": client.Connections{
   657  				Slots: []client.Slot{
   658  					{
   659  						Snap: apiSnapName,
   660  						Name: "network",
   661  					},
   662  				},
   663  			},
   664  		})
   665  	})
   666  	rest, err := Parser(Client()).ParseArgs([]string{"interfaces", cliSnapName})
   667  	c.Assert(err, IsNil)
   668  	c.Assert(rest, DeepEquals, []string{})
   669  	expectedStdout := "" +
   670  		"Slot      Plug\n" +
   671  		":network  -\n"
   672  	c.Assert(s.Stdout(), Equals, expectedStdout)
   673  	c.Assert(s.Stderr(), testutil.EqualsWrapped, InterfacesDeprecationNotice)
   674  }