github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/hookstate/ctlcmd/is_connected_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019 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 ctlcmd_test
    21  
    22  import (
    23  	"github.com/snapcore/snapd/dirs"
    24  	"github.com/snapcore/snapd/overlord/hookstate"
    25  	"github.com/snapcore/snapd/overlord/hookstate/ctlcmd"
    26  	"github.com/snapcore/snapd/overlord/hookstate/hooktest"
    27  	"github.com/snapcore/snapd/overlord/snapstate"
    28  	"github.com/snapcore/snapd/overlord/state"
    29  	"github.com/snapcore/snapd/snap"
    30  	"github.com/snapcore/snapd/snap/snaptest"
    31  	"github.com/snapcore/snapd/testutil"
    32  
    33  	. "gopkg.in/check.v1"
    34  )
    35  
    36  type isConnectedSuite struct {
    37  	testutil.BaseTest
    38  	st          *state.State
    39  	mockHandler *hooktest.MockHandler
    40  }
    41  
    42  var _ = Suite(&isConnectedSuite{})
    43  
    44  func (s *isConnectedSuite) SetUpTest(c *C) {
    45  	s.BaseTest.SetUpTest(c)
    46  	dirs.SetRootDir(c.MkDir())
    47  	s.AddCleanup(func() { dirs.SetRootDir("/") })
    48  	s.st = state.New(nil)
    49  	s.mockHandler = hooktest.NewMockHandler()
    50  }
    51  
    52  var isConnectedTests = []struct {
    53  	args                []string
    54  	stdout, stderr, err string
    55  	exitCode            int
    56  }{{
    57  	args: []string{"is-connected"},
    58  	err:  "the required argument `<plug|slot>` was not provided",
    59  }, {
    60  	args: []string{"is-connected", "plug1"},
    61  }, {
    62  	args: []string{"is-connected", "slot1"},
    63  }, {
    64  	// reported as not connected because of undesired flag
    65  	args:     []string{"is-connected", "plug2"},
    66  	exitCode: 1,
    67  }, {
    68  	// reported as not connected because of hotplug-gone flag
    69  	args:     []string{"is-connected", "plug3"},
    70  	exitCode: 1,
    71  }, {
    72  	args: []string{"is-connected", "slot2"},
    73  	err:  `snap "snap1" has no plug or slot named "slot2"`,
    74  }, {
    75  	args: []string{"is-connected", "foo"},
    76  	err:  `snap "snap1" has no plug or slot named "foo"`,
    77  }}
    78  
    79  func mockInstalledSnap(c *C, st *state.State, snapYaml string) {
    80  	info := snaptest.MockSnapCurrent(c, snapYaml, &snap.SideInfo{Revision: snap.R(1)})
    81  	snapstate.Set(st, info.InstanceName(), &snapstate.SnapState{
    82  		Active: true,
    83  		Sequence: []*snap.SideInfo{
    84  			{
    85  				RealName: info.SnapName(),
    86  				Revision: info.Revision,
    87  				SnapID:   info.InstanceName() + "-id",
    88  			},
    89  		},
    90  		Current: info.Revision,
    91  	})
    92  }
    93  
    94  func (s *isConnectedSuite) testIsConnected(c *C, context *hookstate.Context) {
    95  	mockInstalledSnap(c, s.st, `name: snap1
    96  plugs:
    97    plug1:
    98      interface: x11
    99    plug2:
   100      interface: x11
   101    plug3:
   102      interface: x11
   103  slots:
   104    slot1:
   105      interface: x11`)
   106  
   107  	s.st.Set("conns", map[string]interface{}{
   108  		"snap1:plug1 snap2:slot2": map[string]interface{}{},
   109  		"snap1:plug2 snap3:slot3": map[string]interface{}{"undesired": true},
   110  		"snap1:plug3 snap4:slot4": map[string]interface{}{"hotplug-gone": true},
   111  		"snap3:plug4 snap1:slot1": map[string]interface{}{},
   112  	})
   113  
   114  	s.st.Unlock()
   115  	defer s.st.Lock()
   116  
   117  	for _, test := range isConnectedTests {
   118  		stdout, stderr, err := ctlcmd.Run(context, test.args, 0)
   119  		comment := Commentf("%s", test.args)
   120  		if test.exitCode > 0 {
   121  			c.Check(err, DeepEquals, &ctlcmd.UnsuccessfulError{ExitCode: test.exitCode}, comment)
   122  		} else {
   123  			if test.err == "" {
   124  				c.Check(err, IsNil, comment)
   125  			} else {
   126  				c.Check(err, ErrorMatches, test.err, comment)
   127  			}
   128  		}
   129  
   130  		c.Check(string(stdout), Equals, test.stdout, comment)
   131  		c.Check(string(stderr), Equals, "", comment)
   132  	}
   133  }
   134  
   135  func (s *isConnectedSuite) TestIsConnectedFromHook(c *C) {
   136  	s.st.Lock()
   137  	defer s.st.Unlock()
   138  
   139  	task := s.st.NewTask("test-task", "my test task")
   140  	setup := &hookstate.HookSetup{Snap: "snap1", Revision: snap.R(1), Hook: "test-hook"}
   141  
   142  	mockContext, err := hookstate.NewContext(task, s.st, setup, s.mockHandler, "")
   143  	c.Check(err, IsNil)
   144  
   145  	s.testIsConnected(c, mockContext)
   146  }
   147  
   148  func (s *isConnectedSuite) TestIsConnectedFromApp(c *C) {
   149  	s.st.Lock()
   150  	defer s.st.Unlock()
   151  
   152  	// ephemeral context
   153  	setup := &hookstate.HookSetup{Snap: "snap1", Revision: snap.R(1)}
   154  	mockContext, err := hookstate.NewContext(nil, s.st, setup, s.mockHandler, "")
   155  	c.Check(err, IsNil)
   156  
   157  	// sanity
   158  	c.Assert(mockContext.IsEphemeral(), Equals, true)
   159  
   160  	s.testIsConnected(c, mockContext)
   161  }
   162  
   163  func (s *isConnectedSuite) TestNoContextError(c *C) {
   164  	stdout, stderr, err := ctlcmd.Run(nil, []string{"is-connected", "foo"}, 0)
   165  	c.Check(err, ErrorMatches, `cannot check connection status without a context`)
   166  	c.Check(string(stdout), Equals, "")
   167  	c.Check(string(stderr), Equals, "")
   168  }
   169  
   170  func (s *isConnectedSuite) TestGetRegularUser(c *C) {
   171  	s.st.Lock()
   172  
   173  	mockInstalledSnap(c, s.st, `name: snap1
   174  plugs:
   175    plug1:
   176      interface: x11`)
   177  
   178  	s.st.Set("conns", map[string]interface{}{
   179  		"snap1:plug1 snap2:slot2": map[string]interface{}{},
   180  	})
   181  
   182  	setup := &hookstate.HookSetup{Snap: "snap1", Revision: snap.R(1)}
   183  
   184  	s.st.Unlock()
   185  
   186  	mockContext, err := hookstate.NewContext(nil, s.st, setup, s.mockHandler, "")
   187  	c.Assert(err, IsNil)
   188  	stdout, stderr, err := ctlcmd.Run(mockContext, []string{"is-connected", "plug1"}, 1000)
   189  	c.Check(err, IsNil)
   190  	c.Check(string(stdout), Equals, "")
   191  	c.Check(string(stderr), Equals, "")
   192  }