github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/cmd/snap/cmd_disconnect_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  	"fmt"
    24  	"net/http"
    25  	"os"
    26  
    27  	"github.com/jessevdk/go-flags"
    28  	. "gopkg.in/check.v1"
    29  
    30  	. "github.com/snapcore/snapd/cmd/snap"
    31  )
    32  
    33  func (s *SnapSuite) TestDisconnectHelp(c *C) {
    34  	msg := `Usage:
    35    snap.test disconnect [disconnect-OPTIONS] [<snap>:<plug>] [<snap>:<slot>]
    36  
    37  The disconnect command disconnects a plug from a slot.
    38  It may be called in the following ways:
    39  
    40  $ snap disconnect <snap>:<plug> <snap>:<slot>
    41  
    42  Disconnects the specific plug from the specific slot.
    43  
    44  $ snap disconnect <snap>:<slot or plug>
    45  
    46  Disconnects everything from the provided plug or slot.
    47  The snap name may be omitted for the core snap.
    48  
    49  When an automatic connection is manually disconnected, its disconnected state
    50  is retained after a snap refresh. The --forget flag can be added to the
    51  disconnect command to reset this behaviour, and consequently re-enable
    52  an automatic reconnection after a snap refresh.
    53  
    54  [disconnect command options]
    55        --no-wait          Do not wait for the operation to finish but just print
    56                           the change id.
    57        --forget           Forget remembered state about the given connection.
    58  `
    59  	s.testSubCommandHelp(c, "disconnect", msg)
    60  }
    61  
    62  func (s *SnapSuite) TestDisconnectExplicitEverything(c *C) {
    63  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
    64  		switch r.URL.Path {
    65  		case "/v2/interfaces":
    66  			c.Check(r.Method, Equals, "POST")
    67  			c.Check(DecodedRequestBody(c, r), DeepEquals, map[string]interface{}{
    68  				"action": "disconnect",
    69  				"plugs": []interface{}{
    70  					map[string]interface{}{
    71  						"snap": "producer",
    72  						"plug": "plug",
    73  					},
    74  				},
    75  				"slots": []interface{}{
    76  					map[string]interface{}{
    77  						"snap": "consumer",
    78  						"slot": "slot",
    79  					},
    80  				},
    81  			})
    82  			w.WriteHeader(202)
    83  			fmt.Fprintln(w, `{"type":"async", "status-code": 202, "change": "zzz"}`)
    84  		case "/v2/changes/zzz":
    85  			c.Check(r.Method, Equals, "GET")
    86  			fmt.Fprintln(w, `{"type":"sync", "result":{"ready": true, "status": "Done"}}`)
    87  		default:
    88  			c.Fatalf("unexpected path %q", r.URL.Path)
    89  		}
    90  	})
    91  	rest, err := Parser(Client()).ParseArgs([]string{"disconnect", "producer:plug", "consumer:slot"})
    92  	c.Assert(err, IsNil)
    93  	c.Assert(rest, DeepEquals, []string{})
    94  	c.Assert(s.Stdout(), Equals, "")
    95  	c.Assert(s.Stderr(), Equals, "")
    96  }
    97  
    98  func (s *SnapSuite) TestDisconnectWithForgetFlag(c *C) {
    99  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   100  		switch r.URL.Path {
   101  		case "/v2/interfaces":
   102  			c.Check(r.Method, Equals, "POST")
   103  			c.Check(DecodedRequestBody(c, r), DeepEquals, map[string]interface{}{
   104  				"action": "disconnect",
   105  				"forget": true,
   106  				"plugs": []interface{}{
   107  					map[string]interface{}{
   108  						"snap": "consumer",
   109  						"plug": "plug",
   110  					},
   111  				},
   112  				"slots": []interface{}{
   113  					map[string]interface{}{
   114  						"snap": "producer",
   115  						"slot": "slot",
   116  					},
   117  				},
   118  			})
   119  			w.WriteHeader(202)
   120  			fmt.Fprintln(w, `{"type":"async", "status-code": 202, "change": "zzz"}`)
   121  		case "/v2/changes/zzz":
   122  			c.Check(r.Method, Equals, "GET")
   123  			fmt.Fprintln(w, `{"type":"sync", "result":{"ready": true, "status": "Done"}}`)
   124  		default:
   125  			c.Fatalf("unexpected path %q", r.URL.Path)
   126  		}
   127  	})
   128  	rest, err := Parser(Client()).ParseArgs([]string{"disconnect", "--forget", "consumer:plug", "producer:slot"})
   129  	c.Assert(err, IsNil)
   130  	c.Assert(rest, DeepEquals, []string{})
   131  	c.Assert(s.Stdout(), Equals, "")
   132  	c.Assert(s.Stderr(), Equals, "")
   133  }
   134  
   135  func (s *SnapSuite) TestDisconnectEverythingFromSpecificSlot(c *C) {
   136  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   137  		switch r.URL.Path {
   138  		case "/v2/interfaces":
   139  			c.Check(r.Method, Equals, "POST")
   140  			c.Check(DecodedRequestBody(c, r), DeepEquals, map[string]interface{}{
   141  				"action": "disconnect",
   142  				"plugs": []interface{}{
   143  					map[string]interface{}{
   144  						"snap": "",
   145  						"plug": "",
   146  					},
   147  				},
   148  				"slots": []interface{}{
   149  					map[string]interface{}{
   150  						"snap": "consumer",
   151  						"slot": "slot",
   152  					},
   153  				},
   154  			})
   155  			w.WriteHeader(202)
   156  			fmt.Fprintln(w, `{"type":"async", "status-code": 202, "change": "zzz"}`)
   157  		case "/v2/changes/zzz":
   158  			c.Check(r.Method, Equals, "GET")
   159  			fmt.Fprintln(w, `{"type":"sync", "result":{"ready": true, "status": "Done"}}`)
   160  		default:
   161  			c.Fatalf("unexpected path %q", r.URL.Path)
   162  		}
   163  	})
   164  	rest, err := Parser(Client()).ParseArgs([]string{"disconnect", "consumer:slot"})
   165  	c.Assert(err, IsNil)
   166  	c.Assert(rest, DeepEquals, []string{})
   167  	c.Assert(s.Stdout(), Equals, "")
   168  	c.Assert(s.Stderr(), Equals, "")
   169  }
   170  
   171  func (s *SnapSuite) TestDisconnectEverythingFromSpecificSnapPlugOrSlot(c *C) {
   172  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   173  		switch r.URL.Path {
   174  		case "/v2/interfaces":
   175  			c.Check(r.Method, Equals, "POST")
   176  			c.Check(DecodedRequestBody(c, r), DeepEquals, map[string]interface{}{
   177  				"action": "disconnect",
   178  				"plugs": []interface{}{
   179  					map[string]interface{}{
   180  						"snap": "",
   181  						"plug": "",
   182  					},
   183  				},
   184  				"slots": []interface{}{
   185  					map[string]interface{}{
   186  						"snap": "consumer",
   187  						"slot": "plug-or-slot",
   188  					},
   189  				},
   190  			})
   191  			w.WriteHeader(202)
   192  			fmt.Fprintln(w, `{"type":"async", "status-code": 202, "change": "zzz"}`)
   193  		case "/v2/changes/zzz":
   194  			c.Check(r.Method, Equals, "GET")
   195  			fmt.Fprintln(w, `{"type":"sync", "result":{"ready": true, "status": "Done"}}`)
   196  		default:
   197  			c.Fatalf("unexpected path %q", r.URL.Path)
   198  		}
   199  	})
   200  	rest, err := Parser(Client()).ParseArgs([]string{"disconnect", "consumer:plug-or-slot"})
   201  	c.Assert(err, IsNil)
   202  	c.Assert(rest, DeepEquals, []string{})
   203  	c.Assert(s.Stdout(), Equals, "")
   204  	c.Assert(s.Stderr(), Equals, "")
   205  }
   206  
   207  func (s *SnapSuite) TestDisconnectEverythingFromSpecificSnap(c *C) {
   208  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   209  		c.Fatalf("expected nothing to reach the server")
   210  	})
   211  	rest, err := Parser(Client()).ParseArgs([]string{"disconnect", "consumer"})
   212  	c.Assert(err, ErrorMatches, `please provide the plug or slot name to disconnect from snap "consumer"`)
   213  	c.Assert(rest, DeepEquals, []string{"consumer"})
   214  	c.Assert(s.Stdout(), Equals, "")
   215  	c.Assert(s.Stderr(), Equals, "")
   216  }
   217  
   218  func (s *SnapSuite) TestDisconnectCompletion(c *C) {
   219  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   220  		switch r.URL.Path {
   221  		case "/v2/connections":
   222  			c.Assert(r.Method, Equals, "GET")
   223  			EncodeResponseBody(c, w, map[string]interface{}{
   224  				"type":   "sync",
   225  				"result": fortestingConnectionList,
   226  			})
   227  		default:
   228  			c.Fatalf("unexpected path %q", r.URL.Path)
   229  		}
   230  	})
   231  	os.Setenv("GO_FLAGS_COMPLETION", "verbose")
   232  	defer os.Unsetenv("GO_FLAGS_COMPLETION")
   233  
   234  	expected := []flags.Completion{}
   235  	parser := Parser(Client())
   236  	parser.CompletionHandler = func(obtained []flags.Completion) {
   237  		c.Check(obtained, DeepEquals, expected)
   238  	}
   239  
   240  	expected = []flags.Completion{{Item: "canonical-pi2:"}, {Item: "core:"}, {Item: "keyboard-lights:"}}
   241  	_, err := parser.ParseArgs([]string{"disconnect", ""})
   242  	c.Assert(err, IsNil)
   243  
   244  	expected = []flags.Completion{{Item: "canonical-pi2:pin-13", Description: "slot"}}
   245  	_, err = parser.ParseArgs([]string{"disconnect", "ca"})
   246  	c.Assert(err, IsNil)
   247  
   248  	expected = []flags.Completion{{Item: ":core-support", Description: "slot"}, {Item: ":core-support-plug", Description: "plug"}}
   249  	_, err = parser.ParseArgs([]string{"disconnect", ":"})
   250  	c.Assert(err, IsNil)
   251  
   252  	expected = []flags.Completion{{Item: "keyboard-lights:capslock-led", Description: "plug"}}
   253  	_, err = parser.ParseArgs([]string{"disconnect", "k"})
   254  	c.Assert(err, IsNil)
   255  
   256  	expected = []flags.Completion{{Item: "canonical-pi2:"}, {Item: "core:"}}
   257  	_, err = parser.ParseArgs([]string{"disconnect", "keyboard-lights:capslock-led", ""})
   258  	c.Assert(err, IsNil)
   259  
   260  	expected = []flags.Completion{{Item: "canonical-pi2:pin-13", Description: "slot"}}
   261  	_, err = parser.ParseArgs([]string{"disconnect", "keyboard-lights:capslock-led", "ca"})
   262  	c.Assert(err, IsNil)
   263  
   264  	expected = []flags.Completion{{Item: ":core-support", Description: "slot"}}
   265  	_, err = parser.ParseArgs([]string{"disconnect", ":core-support-plug", ":"})
   266  	c.Assert(err, IsNil)
   267  
   268  	c.Assert(s.Stdout(), Equals, "")
   269  	c.Assert(s.Stderr(), Equals, "")
   270  }