github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/plugin/rpc/cli_rpc_server_test.go (about)

     1  package rpc_test
     2  
     3  import (
     4  	"net"
     5  	"net/rpc"
     6  	"time"
     7  
     8  	"github.com/cloudfoundry/cli/cf/terminal/fakes"
     9  	"github.com/cloudfoundry/cli/plugin"
    10  	. "github.com/cloudfoundry/cli/plugin/rpc"
    11  	io_helpers "github.com/cloudfoundry/cli/testhelpers/io"
    12  	"github.com/codegangsta/cli"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Server", func() {
    18  	var (
    19  		err        error
    20  		client     *rpc.Client
    21  		rpcService *CliRpcService
    22  	)
    23  
    24  	AfterEach(func() {
    25  		if client != nil {
    26  			client.Close()
    27  		}
    28  	})
    29  
    30  	BeforeEach(func() {
    31  		rpc.DefaultServer = rpc.NewServer()
    32  	})
    33  
    34  	Describe(".NewRpcService", func() {
    35  		BeforeEach(func() {
    36  			rpcService, err = NewRpcService(nil, nil, nil)
    37  			Expect(err).ToNot(HaveOccurred())
    38  		})
    39  
    40  		It("returns an err of another Rpc process is already registered", func() {
    41  			_, err := NewRpcService(nil, nil, nil)
    42  			Expect(err).To(HaveOccurred())
    43  		})
    44  	})
    45  
    46  	Describe(".Stop", func() {
    47  		BeforeEach(func() {
    48  			rpcService, err = NewRpcService(nil, nil, nil)
    49  			Expect(err).ToNot(HaveOccurred())
    50  
    51  			err := rpcService.Start()
    52  			Expect(err).ToNot(HaveOccurred())
    53  
    54  			pingCli(rpcService.Port())
    55  		})
    56  
    57  		It("shuts down the rpc server", func() {
    58  			rpcService.Stop()
    59  
    60  			//give time for server to stop
    61  			time.Sleep(50 * time.Millisecond)
    62  
    63  			client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
    64  			Expect(err).To(HaveOccurred())
    65  		})
    66  	})
    67  
    68  	Describe(".Start", func() {
    69  		BeforeEach(func() {
    70  			rpcService, err = NewRpcService(nil, nil, nil)
    71  			Expect(err).ToNot(HaveOccurred())
    72  
    73  			err := rpcService.Start()
    74  			Expect(err).ToNot(HaveOccurred())
    75  
    76  			pingCli(rpcService.Port())
    77  		})
    78  
    79  		AfterEach(func() {
    80  			rpcService.Stop()
    81  
    82  			//give time for server to stop
    83  			time.Sleep(50 * time.Millisecond)
    84  		})
    85  
    86  		It("Start an Rpc server for communication", func() {
    87  			client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
    88  			Expect(err).ToNot(HaveOccurred())
    89  		})
    90  	})
    91  
    92  	Describe(".SetPluginMetadata", func() {
    93  		var (
    94  			metadata *plugin.PluginMetadata
    95  		)
    96  
    97  		BeforeEach(func() {
    98  			rpcService, err = NewRpcService(nil, nil, nil)
    99  			Expect(err).ToNot(HaveOccurred())
   100  
   101  			err := rpcService.Start()
   102  			Expect(err).ToNot(HaveOccurred())
   103  
   104  			pingCli(rpcService.Port())
   105  
   106  			client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   107  			Expect(err).ToNot(HaveOccurred())
   108  
   109  			metadata = &plugin.PluginMetadata{
   110  				Name: "foo",
   111  				Commands: []plugin.Command{
   112  					{Name: "cmd_1", HelpText: "cm 1 help text"},
   113  					{Name: "cmd_2", HelpText: "cmd 2 help text"},
   114  				},
   115  			}
   116  		})
   117  
   118  		AfterEach(func() {
   119  			rpcService.Stop()
   120  
   121  			//give time for server to stop
   122  			time.Sleep(50 * time.Millisecond)
   123  		})
   124  
   125  		It("set the rpc command's Return Data", func() {
   126  			var success bool
   127  			err = client.Call("CliRpcCmd.SetPluginMetadata", metadata, &success)
   128  
   129  			Expect(err).ToNot(HaveOccurred())
   130  			Expect(success).To(BeTrue())
   131  			Expect(rpcService.RpcCmd.PluginMetadata).To(Equal(metadata))
   132  		})
   133  	})
   134  
   135  	Describe(".GetOutputAndReset", func() {
   136  		Context("success", func() {
   137  			BeforeEach(func() {
   138  				outputCapture := &fakes.FakeOutputCapture{}
   139  				outputCapture.GetOutputAndResetReturns([]string{"hi from command"})
   140  				rpcService, err = NewRpcService(nil, outputCapture, nil)
   141  				Expect(err).ToNot(HaveOccurred())
   142  
   143  				err := rpcService.Start()
   144  				Expect(err).ToNot(HaveOccurred())
   145  
   146  				pingCli(rpcService.Port())
   147  			})
   148  
   149  			AfterEach(func() {
   150  				rpcService.Stop()
   151  
   152  				//give time for server to stop
   153  				time.Sleep(50 * time.Millisecond)
   154  			})
   155  
   156  			It("should return the logs from the output capture", func() {
   157  				client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   158  				Expect(err).ToNot(HaveOccurred())
   159  				var output []string
   160  				client.Call("CliRpcCmd.GetOutputAndReset", false, &output)
   161  
   162  				Expect(output).To(Equal([]string{"hi from command"}))
   163  			})
   164  		})
   165  	})
   166  
   167  	Describe("disabling terminal output", func() {
   168  		var terminalOutputSwitch *fakes.FakeTerminalOutputSwitch
   169  
   170  		BeforeEach(func() {
   171  			terminalOutputSwitch = &fakes.FakeTerminalOutputSwitch{}
   172  			rpcService, err = NewRpcService(nil, nil, terminalOutputSwitch)
   173  			Expect(err).ToNot(HaveOccurred())
   174  
   175  			err := rpcService.Start()
   176  			Expect(err).ToNot(HaveOccurred())
   177  
   178  			pingCli(rpcService.Port())
   179  		})
   180  
   181  		It("should disable the terminal output switch", func() {
   182  			client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   183  			Expect(err).ToNot(HaveOccurred())
   184  
   185  			var success bool
   186  			err = client.Call("CliRpcCmd.DisableTerminalOutput", true, &success)
   187  
   188  			Expect(err).ToNot(HaveOccurred())
   189  			Expect(success).To(BeTrue())
   190  			Expect(terminalOutputSwitch.DisableTerminalOutputCallCount()).To(Equal(1))
   191  			Expect(terminalOutputSwitch.DisableTerminalOutputArgsForCall(0)).To(Equal(true))
   192  		})
   193  	})
   194  
   195  	Describe(".CallCoreCommand", func() {
   196  		Context("success", func() {
   197  			BeforeEach(func() {
   198  				app := &cli.App{
   199  					Commands: []cli.Command{
   200  						{
   201  							Name:        "test_cmd",
   202  							Description: "test_cmd description",
   203  							Usage:       "test_cmd usage",
   204  							Action: func(context *cli.Context) {
   205  								return
   206  							},
   207  						},
   208  					},
   209  				}
   210  
   211  				outputCapture := &fakes.FakeOutputCapture{}
   212  
   213  				rpcService, err = NewRpcService(app, outputCapture, nil)
   214  				Expect(err).ToNot(HaveOccurred())
   215  
   216  				err := rpcService.Start()
   217  				Expect(err).ToNot(HaveOccurred())
   218  
   219  				pingCli(rpcService.Port())
   220  			})
   221  
   222  			AfterEach(func() {
   223  				rpcService.Stop()
   224  
   225  				//give time for server to stop
   226  				time.Sleep(50 * time.Millisecond)
   227  			})
   228  
   229  			It("calls the code gangsta cli App command", func() {
   230  				client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   231  				Expect(err).ToNot(HaveOccurred())
   232  
   233  				var success bool
   234  				err = client.Call("CliRpcCmd.CallCoreCommand", []string{"test_cmd"}, &success)
   235  
   236  				Expect(err).ToNot(HaveOccurred())
   237  				Expect(success).To(BeTrue())
   238  			})
   239  		})
   240  
   241  		Context("fail", func() {
   242  			BeforeEach(func() {
   243  				app := &cli.App{
   244  					Commands: []cli.Command{
   245  						{
   246  							Name:        "test_cmd",
   247  							Description: "test_cmd description",
   248  							Usage:       "test_cmd usage",
   249  							Action: func(context *cli.Context) {
   250  								panic("ERROR")
   251  							},
   252  						},
   253  					},
   254  				}
   255  				outputCapture := &fakes.FakeOutputCapture{}
   256  				rpcService, err = NewRpcService(app, outputCapture, nil)
   257  				Expect(err).ToNot(HaveOccurred())
   258  
   259  				err := rpcService.Start()
   260  				Expect(err).ToNot(HaveOccurred())
   261  
   262  				pingCli(rpcService.Port())
   263  			})
   264  
   265  			It("returns false in success if the command cannot be found", func() {
   266  				io_helpers.CaptureOutput(func() {
   267  					client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   268  					Expect(err).ToNot(HaveOccurred())
   269  
   270  					var success bool
   271  					err = client.Call("CliRpcCmd.CallCoreCommand", []string{"not_a_cmd"}, &success)
   272  					Expect(success).To(BeFalse())
   273  					Expect(err).ToNot(HaveOccurred())
   274  				})
   275  			})
   276  
   277  			It("returns an error if a command cannot parse provided flags", func() {
   278  				io_helpers.CaptureOutput(func() {
   279  					client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   280  					Expect(err).ToNot(HaveOccurred())
   281  
   282  					var success bool
   283  					err = client.Call("CliRpcCmd.CallCoreCommand", []string{"test_cmd", "-invalid_flag"}, &success)
   284  
   285  					Expect(err).To(HaveOccurred())
   286  					Expect(success).To(BeFalse())
   287  				})
   288  			})
   289  
   290  			It("recovers from a panic from any core command", func() {
   291  				client, err = rpc.Dial("tcp", "127.0.0.1:"+rpcService.Port())
   292  				Expect(err).ToNot(HaveOccurred())
   293  
   294  				var success bool
   295  				err = client.Call("CliRpcCmd.CallCoreCommand", []string{"test_cmd"}, &success)
   296  
   297  				Expect(success).To(BeFalse())
   298  			})
   299  		})
   300  	})
   301  })
   302  
   303  func pingCli(port string) {
   304  	var connErr error
   305  	var conn net.Conn
   306  	for i := 0; i < 5; i++ {
   307  		conn, connErr = net.Dial("tcp", "127.0.0.1:"+port)
   308  		if connErr != nil {
   309  			time.Sleep(200 * time.Millisecond)
   310  		} else {
   311  			conn.Close()
   312  			break
   313  		}
   314  	}
   315  	Expect(connErr).ToNot(HaveOccurred())
   316  }