github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/integration/integration_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  
     8  	"google.golang.org/grpc"
     9  
    10  	"github.com/mutagen-io/mutagen/cmd"
    11  	"github.com/mutagen-io/mutagen/pkg/agent"
    12  	"github.com/mutagen-io/mutagen/pkg/daemon"
    13  	"github.com/mutagen-io/mutagen/pkg/forwarding"
    14  	"github.com/mutagen-io/mutagen/pkg/grpcutil"
    15  	"github.com/mutagen-io/mutagen/pkg/ipc"
    16  	daemonsvc "github.com/mutagen-io/mutagen/pkg/service/daemon"
    17  	forwardingsvc "github.com/mutagen-io/mutagen/pkg/service/forwarding"
    18  	promptingsvc "github.com/mutagen-io/mutagen/pkg/service/prompting"
    19  	synchronizationsvc "github.com/mutagen-io/mutagen/pkg/service/synchronization"
    20  	"github.com/mutagen-io/mutagen/pkg/synchronization"
    21  
    22  	// Explicitly import packages that need to register protocol handlers.
    23  	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/docker"
    24  	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/local"
    25  	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/ssh"
    26  	_ "github.com/mutagen-io/mutagen/pkg/integration/protocols/netpipe"
    27  	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/docker"
    28  	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/local"
    29  	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/ssh"
    30  )
    31  
    32  // forwardingManager is the forwarding session manager for the integration
    33  // testing daemon. It is exposed for integration tests that operate at the API
    34  // level (as opposed to the gRPC or command line level).
    35  var forwardingManager *forwarding.Manager
    36  
    37  // synchronizationManager is the synchronization session manager for the
    38  // integration testing daemon. It is exposed for integration tests that operate
    39  // at the API level (as opposed to the gRPC or command line level).
    40  var synchronizationManager *synchronization.Manager
    41  
    42  // TestMain is the entry point for integration tests. It replaces the default
    43  // test entry point so that it can copy the mutagen executable to a well-known
    44  // path, set up the agent bundle to work during testing, set up a functionally
    45  // complete daemon instance for testing, and tear down all of the aforementioned
    46  // infrastructure after running tests.
    47  func TestMain(m *testing.M) {
    48  	// Override the expected agent bundle location.
    49  	agent.ExpectedBundleLocation = agent.BundleLocationBuildDirectory
    50  
    51  	// Acquire the daemon lock and defer its release.
    52  	lock, err := daemon.AcquireLock()
    53  	if err != nil {
    54  		cmd.Fatal(fmt.Errorf("unable to acquire daemon lock: %w", err))
    55  	}
    56  	defer lock.Release()
    57  
    58  	// Create a forwarding session manager and defer its shutdown.
    59  	forwardingManager, err = forwarding.NewManager(nil)
    60  	if err != nil {
    61  		cmd.Fatal(fmt.Errorf("unable to create forwarding session manager: %w", err))
    62  	}
    63  	defer forwardingManager.Shutdown()
    64  
    65  	// Create a session manager and defer its shutdown.
    66  	synchronizationManager, err = synchronization.NewManager(nil)
    67  	if err != nil {
    68  		cmd.Fatal(fmt.Errorf("unable to create synchronization session manager: %w", err))
    69  	}
    70  	defer synchronizationManager.Shutdown()
    71  
    72  	// Create the gRPC server and defer its termination. We use a hard stop
    73  	// rather than a graceful stop so that it doesn't hang on open requests.
    74  	server := grpc.NewServer(
    75  		grpc.MaxSendMsgSize(grpcutil.MaximumMessageSize),
    76  		grpc.MaxRecvMsgSize(grpcutil.MaximumMessageSize),
    77  	)
    78  	defer server.Stop()
    79  
    80  	// Create and register the daemon service and defer its shutdown.
    81  	daemonServer := daemonsvc.NewServer()
    82  	daemonsvc.RegisterDaemonServer(server, daemonServer)
    83  	defer daemonServer.Shutdown()
    84  
    85  	// Create and register the prompt service.
    86  	promptingsvc.RegisterPromptingServer(server, promptingsvc.NewServer())
    87  
    88  	// Create and register the forwarding server.
    89  	forwardingServer := forwardingsvc.NewServer(forwardingManager)
    90  	forwardingsvc.RegisterForwardingServer(server, forwardingServer)
    91  
    92  	// Create and register the session service.
    93  	synchronizationServer := synchronizationsvc.NewServer(synchronizationManager)
    94  	synchronizationsvc.RegisterSynchronizationServer(server, synchronizationServer)
    95  
    96  	// Compute the path to the daemon IPC endpoint.
    97  	endpoint, err := daemon.EndpointPath()
    98  	if err != nil {
    99  		cmd.Fatal(fmt.Errorf("unable to compute endpoint path: %w", err))
   100  	}
   101  
   102  	// Create the daemon listener and defer its closure. Since we hold the
   103  	// daemon lock, we preemptively remove any existing socket since it (should)
   104  	// be stale.
   105  	os.Remove(endpoint)
   106  	listener, err := ipc.NewListener(endpoint)
   107  	if err != nil {
   108  		cmd.Fatal(fmt.Errorf("unable to create daemon listener: %w", err))
   109  	}
   110  	defer listener.Close()
   111  
   112  	// Serve incoming connections in a separate Goroutine. We don't monitor for
   113  	// errors since there's nothing that we can do about them and because
   114  	// they'll likely show up in the test output anyway.
   115  	go server.Serve(listener)
   116  
   117  	// Run tests.
   118  	m.Run()
   119  }