github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/testutil/dbustest.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2015 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 testutil
    21  
    22  import (
    23  	"bufio"
    24  	"fmt"
    25  	"io/ioutil"
    26  	"os"
    27  	"os/exec"
    28  	"path/filepath"
    29  
    30  	"github.com/godbus/dbus"
    31  	. "gopkg.in/check.v1"
    32  
    33  	"github.com/snapcore/snapd/dbusutil"
    34  )
    35  
    36  // DBusTest provides a separate dbus session bus for running tests
    37  type DBusTest struct {
    38  	tmpdir           string
    39  	dbusDaemon       *exec.Cmd
    40  	oldSessionBusEnv string
    41  
    42  	// the dbus.Conn to the session bus that tests can use
    43  	SessionBus *dbus.Conn
    44  }
    45  
    46  // sessionBusConfigTemplate is a minimal session dbus daemon
    47  // configuration template for use in the unit tests. In comparison to
    48  // the typical disto session config, it contains no <servicedir>
    49  // directives to avoid activating services installed on the test
    50  // system.
    51  const sessionBusConfigTemplate = `<busconfig>
    52    <type>session</type>
    53    <listen>unix:path=%s/user_bus_socket</listen>
    54    <auth>EXTERNAL</auth>
    55    <policy context="default">
    56      <!-- Allow everything to be sent -->
    57      <allow send_destination="*" eavesdrop="true"/>
    58      <!-- Allow everything to be received -->
    59      <allow eavesdrop="true"/>
    60      <!-- Allow anyone to own anything -->
    61      <allow own="*"/>
    62    </policy>
    63  </busconfig>
    64  `
    65  
    66  func (s *DBusTest) SetUpSuite(c *C) {
    67  	if _, err := exec.LookPath("dbus-daemon"); err != nil {
    68  		c.Skip(fmt.Sprintf("cannot run test without dbus-daemon: %s", err))
    69  		return
    70  	}
    71  	if _, err := exec.LookPath("dbus-launch"); err != nil {
    72  		c.Skip(fmt.Sprintf("cannot run test without dbus-launch: %s", err))
    73  		return
    74  	}
    75  
    76  	s.tmpdir = c.MkDir()
    77  	configFile := filepath.Join(s.tmpdir, "session.conf")
    78  	err := ioutil.WriteFile(configFile, []byte(fmt.Sprintf(sessionBusConfigTemplate, s.tmpdir)), 0644)
    79  	c.Assert(err, IsNil)
    80  	s.dbusDaemon = exec.Command("dbus-daemon", "--print-address", fmt.Sprintf("--config-file=%s", configFile))
    81  	s.dbusDaemon.Stderr = os.Stderr
    82  	pout, err := s.dbusDaemon.StdoutPipe()
    83  	c.Assert(err, IsNil)
    84  	err = s.dbusDaemon.Start()
    85  	c.Assert(err, IsNil)
    86  
    87  	scanner := bufio.NewScanner(pout)
    88  	scanner.Scan()
    89  	c.Assert(scanner.Err(), IsNil)
    90  	s.oldSessionBusEnv = os.Getenv("DBUS_SESSION_BUS_ADDRESS")
    91  	os.Setenv("DBUS_SESSION_BUS_ADDRESS", scanner.Text())
    92  
    93  	s.SessionBus, err = dbusutil.SessionBusPrivate()
    94  	c.Assert(err, IsNil)
    95  }
    96  
    97  func (s *DBusTest) TearDownSuite(c *C) {
    98  	if s.SessionBus != nil {
    99  		s.SessionBus.Close()
   100  	}
   101  
   102  	os.Setenv("DBUS_SESSION_BUS_ADDRESS", s.oldSessionBusEnv)
   103  	if s.dbusDaemon != nil && s.dbusDaemon.Process != nil {
   104  		err := s.dbusDaemon.Process.Kill()
   105  		c.Assert(err, IsNil)
   106  		err = s.dbusDaemon.Wait() // do cleanup
   107  		c.Assert(err, ErrorMatches, `(?i)signal: killed`)
   108  	}
   109  }
   110  
   111  func (s *DBusTest) SetUpTest(c *C)    {}
   112  func (s *DBusTest) TearDownTest(c *C) {}
   113  
   114  func DBusGetConnectionUnixProcessID(conn *dbus.Conn, name string) (pid int, err error) {
   115  	obj := conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
   116  
   117  	err = obj.Call("org.freedesktop.DBus.GetConnectionUnixProcessID", 0, name).Store(&pid)
   118  	return pid, err
   119  }