github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/packer/rpc/communicator_test.go (about)

     1  package rpc
     2  
     3  import (
     4  	"bufio"
     5  	"cgl.tideland.biz/asserts"
     6  	"github.com/mitchellh/packer/packer"
     7  	"io"
     8  	"net/rpc"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  type testCommunicator struct {
    14  	startCalled bool
    15  	startCmd    *packer.RemoteCmd
    16  
    17  	uploadCalled bool
    18  	uploadPath   string
    19  	uploadData   string
    20  
    21  	downloadCalled bool
    22  	downloadPath   string
    23  }
    24  
    25  func (t *testCommunicator) Start(cmd *packer.RemoteCmd) error {
    26  	t.startCalled = true
    27  	t.startCmd = cmd
    28  	return nil
    29  }
    30  
    31  func (t *testCommunicator) Upload(path string, reader io.Reader) (err error) {
    32  	t.uploadCalled = true
    33  	t.uploadPath = path
    34  	t.uploadData, err = bufio.NewReader(reader).ReadString('\n')
    35  	return
    36  }
    37  
    38  func (t *testCommunicator) Download(path string, writer io.Writer) error {
    39  	t.downloadCalled = true
    40  	t.downloadPath = path
    41  	writer.Write([]byte("download\n"))
    42  
    43  	return nil
    44  }
    45  
    46  func TestCommunicatorRPC(t *testing.T) {
    47  	assert := asserts.NewTestingAsserts(t, true)
    48  
    49  	// Create the interface to test
    50  	c := new(testCommunicator)
    51  
    52  	// Start the server
    53  	server := rpc.NewServer()
    54  	RegisterCommunicator(server, c)
    55  	address := serveSingleConn(server)
    56  
    57  	// Create the client over RPC and run some methods to verify it works
    58  	client, err := rpc.Dial("tcp", address)
    59  	assert.Nil(err, "should be able to connect")
    60  	remote := Communicator(client)
    61  
    62  	// The remote command we'll use
    63  	stdin_r, stdin_w := io.Pipe()
    64  	stdout_r, stdout_w := io.Pipe()
    65  	stderr_r, stderr_w := io.Pipe()
    66  
    67  	var cmd packer.RemoteCmd
    68  	cmd.Command = "foo"
    69  	cmd.Stdin = stdin_r
    70  	cmd.Stdout = stdout_w
    71  	cmd.Stderr = stderr_w
    72  
    73  	// Test Start
    74  	err = remote.Start(&cmd)
    75  	assert.Nil(err, "should not have an error")
    76  
    77  	// Test that we can read from stdout
    78  	c.startCmd.Stdout.Write([]byte("outfoo\n"))
    79  	bufOut := bufio.NewReader(stdout_r)
    80  	data, err := bufOut.ReadString('\n')
    81  	assert.Nil(err, "should have no problem reading stdout")
    82  	assert.Equal(data, "outfoo\n", "should be correct stdout")
    83  
    84  	// Test that we can read from stderr
    85  	c.startCmd.Stderr.Write([]byte("errfoo\n"))
    86  	bufErr := bufio.NewReader(stderr_r)
    87  	data, err = bufErr.ReadString('\n')
    88  	assert.Nil(err, "should have no problem reading stderr")
    89  	assert.Equal(data, "errfoo\n", "should be correct stderr")
    90  
    91  	// Test that we can write to stdin
    92  	stdin_w.Write([]byte("infoo\n"))
    93  	bufIn := bufio.NewReader(c.startCmd.Stdin)
    94  	data, err = bufIn.ReadString('\n')
    95  	assert.Nil(err, "should have no problem reading stdin")
    96  	assert.Equal(data, "infoo\n", "should be correct stdin")
    97  
    98  	// Test that we can get the exit status properly
    99  	c.startCmd.SetExited(42)
   100  
   101  	for i := 0; i < 5; i++ {
   102  		if cmd.Exited {
   103  			assert.Equal(cmd.ExitStatus, 42, "should have proper exit status")
   104  			break
   105  		}
   106  
   107  		time.Sleep(50 * time.Millisecond)
   108  	}
   109  
   110  	assert.True(cmd.Exited, "should have exited")
   111  
   112  	// Test that we can upload things
   113  	uploadR, uploadW := io.Pipe()
   114  	go uploadW.Write([]byte("uploadfoo\n"))
   115  	err = remote.Upload("foo", uploadR)
   116  	assert.Nil(err, "should not error")
   117  	assert.True(c.uploadCalled, "should be called")
   118  	assert.Equal(c.uploadPath, "foo", "should be correct path")
   119  	assert.Equal(c.uploadData, "uploadfoo\n", "should have the proper data")
   120  
   121  	// Test that we can download things
   122  	downloadR, downloadW := io.Pipe()
   123  	downloadDone := make(chan bool)
   124  	var downloadData string
   125  	var downloadErr error
   126  
   127  	go func() {
   128  		bufDownR := bufio.NewReader(downloadR)
   129  		downloadData, downloadErr = bufDownR.ReadString('\n')
   130  		downloadDone <- true
   131  	}()
   132  
   133  	err = remote.Download("bar", downloadW)
   134  	assert.Nil(err, "should not error")
   135  	assert.True(c.downloadCalled, "should have called download")
   136  	assert.Equal(c.downloadPath, "bar", "should have correct download path")
   137  
   138  	<-downloadDone
   139  	assert.Nil(downloadErr, "should not error reading download data")
   140  	assert.Equal(downloadData, "download\n", "should have the proper data")
   141  }
   142  
   143  func TestCommunicator_ImplementsCommunicator(t *testing.T) {
   144  	assert := asserts.NewTestingAsserts(t, true)
   145  
   146  	var r packer.Communicator
   147  	c := Communicator(nil)
   148  
   149  	assert.Implementor(c, &r, "should be a Communicator")
   150  }