LEFT | RIGHT |
1 package server_test | 1 package server_test |
2 | 2 |
3 import ( | 3 import ( |
4 "errors" | 4 "errors" |
5 "fmt" | 5 "fmt" |
6 "io/ioutil" | 6 "io/ioutil" |
7 "launchpad.net/gnuflag" | 7 "launchpad.net/gnuflag" |
8 . "launchpad.net/gocheck" | 8 . "launchpad.net/gocheck" |
9 "launchpad.net/juju/go/cmd" | 9 "launchpad.net/juju/go/cmd" |
10 "launchpad.net/juju/go/cmd/jujuc/server" | 10 "launchpad.net/juju/go/cmd/jujuc/server" |
11 "net/rpc" | 11 "net/rpc" |
12 "os" | 12 "os" |
13 "path/filepath" | 13 "path/filepath" |
14 "strings" | |
15 ) | 14 ) |
16 | 15 |
17 type RpcCommand struct { | 16 type RpcCommand struct { |
18 Value string | 17 Value string |
19 } | 18 } |
20 | 19 |
21 func (c *RpcCommand) Info() *cmd.Info { | 20 func (c *RpcCommand) Info() *cmd.Info { |
22 » return &cmd.Info{"magic", "", "do magic", "blah doc"} | 21 » return &cmd.Info{"remote", "", "act at a distance", "blah doc"} |
23 } | 22 } |
24 | 23 |
25 func (c *RpcCommand) Init(f *gnuflag.FlagSet, args []string) error { | 24 func (c *RpcCommand) Init(f *gnuflag.FlagSet, args []string) error { |
26 f.StringVar(&c.Value, "value", "", "doc") | 25 f.StringVar(&c.Value, "value", "", "doc") |
27 if err := f.Parse(true, args); err != nil { | 26 if err := f.Parse(true, args); err != nil { |
28 return err | 27 return err |
29 } | 28 } |
30 return cmd.CheckEmpty(f.Args()) | 29 return cmd.CheckEmpty(f.Args()) |
31 } | 30 } |
32 | 31 |
33 func (c *RpcCommand) Run(ctx *cmd.Context) error { | 32 func (c *RpcCommand) Run(ctx *cmd.Context) error { |
34 » if c.Value != "zyxxy" { | 33 » if c.Value == "error" { |
35 » » return errors.New("insufficiently magic") | 34 » » return errors.New("blam") |
36 } | 35 } |
37 ctx.Stdout.Write([]byte("eye of newt\n")) | 36 ctx.Stdout.Write([]byte("eye of newt\n")) |
38 ctx.Stderr.Write([]byte("toe of frog\n")) | 37 ctx.Stderr.Write([]byte("toe of frog\n")) |
39 » return ioutil.WriteFile(ctx.AbsPath("local"), []byte{}, 0644) | 38 » return ioutil.WriteFile(ctx.AbsPath("local"), []byte(c.Value), 0644) |
40 } | 39 } |
41 | 40 |
42 func factory(contextId, cmdName string) (cmd.Command, error) { | 41 func factory(contextId, cmdName string) (cmd.Command, error) { |
43 » if contextId != "merlin" { | 42 » if contextId != "validCtx" { |
44 » » return nil, errors.New("unknown client") | 43 » » return nil, fmt.Errorf("unknown context %q", contextId) |
45 } | 44 } |
46 » if cmdName != "magic" { | 45 » if cmdName != "remote" { |
47 return nil, fmt.Errorf("unknown command %q", cmdName) | 46 return nil, fmt.Errorf("unknown command %q", cmdName) |
48 } | 47 } |
49 return &RpcCommand{}, nil | 48 return &RpcCommand{}, nil |
50 } | 49 } |
51 | 50 |
52 type ServerSuite struct { | 51 type ServerSuite struct { |
53 server *server.Server | 52 server *server.Server |
54 sockPath string | 53 sockPath string |
55 err chan error | 54 err chan error |
56 } | 55 } |
(...skipping 21 matching lines...) Expand all Loading... |
78 client, err := rpc.Dial("unix", s.sockPath) | 77 client, err := rpc.Dial("unix", s.sockPath) |
79 c.Assert(err, IsNil) | 78 c.Assert(err, IsNil) |
80 defer client.Close() | 79 defer client.Close() |
81 err = client.Call("Jujuc.Main", req, &resp) | 80 err = client.Call("Jujuc.Main", req, &resp) |
82 return resp, err | 81 return resp, err |
83 } | 82 } |
84 | 83 |
85 func (s *ServerSuite) TestHappyPath(c *C) { | 84 func (s *ServerSuite) TestHappyPath(c *C) { |
86 dir := c.MkDir() | 85 dir := c.MkDir() |
87 resp, err := s.Call(c, server.Request{ | 86 resp, err := s.Call(c, server.Request{ |
88 » » "merlin", dir, "magic", []string{"--value", "zyxxy"}}) | 87 » » "validCtx", dir, "remote", []string{"--value", "something"}}) |
89 c.Assert(err, IsNil) | 88 c.Assert(err, IsNil) |
90 c.Assert(resp.Code, Equals, 0) | 89 c.Assert(resp.Code, Equals, 0) |
91 c.Assert(string(resp.Stdout), Equals, "eye of newt\n") | 90 c.Assert(string(resp.Stdout), Equals, "eye of newt\n") |
92 c.Assert(string(resp.Stderr), Equals, "toe of frog\n") | 91 c.Assert(string(resp.Stderr), Equals, "toe of frog\n") |
93 » _, err = os.Stat(filepath.Join(dir, "local")) | 92 » content, err := ioutil.ReadFile(filepath.Join(dir, "local")) |
94 c.Assert(err, IsNil) | 93 c.Assert(err, IsNil) |
| 94 c.Assert(string(content), Equals, "something") |
95 } | 95 } |
96 | 96 |
97 func (s *ServerSuite) TestBadCommandName(c *C) { | 97 func (s *ServerSuite) TestBadCommandName(c *C) { |
98 dir := c.MkDir() | 98 dir := c.MkDir() |
99 » _, err := s.Call(c, server.Request{"merlin", dir, "", nil}) | 99 » _, err := s.Call(c, server.Request{"validCtx", dir, "", nil}) |
100 c.Assert(err, ErrorMatches, "bad request: command not specified") | 100 c.Assert(err, ErrorMatches, "bad request: command not specified") |
101 » _, err = s.Call(c, server.Request{"merlin", dir, "witchcraft", nil}) | 101 » _, err = s.Call(c, server.Request{"validCtx", dir, "witchcraft", nil}) |
102 c.Assert(err, ErrorMatches, `bad request: unknown command "witchcraft"`) | 102 c.Assert(err, ErrorMatches, `bad request: unknown command "witchcraft"`) |
103 } | 103 } |
104 | 104 |
105 func (s *ServerSuite) TestBadDir(c *C) { | 105 func (s *ServerSuite) TestBadDir(c *C) { |
106 for _, req := range []server.Request{ | 106 for _, req := range []server.Request{ |
107 » » {"merlin", "", "cmd", nil}, | 107 » » {"validCtx", "", "anything", nil}, |
108 » » {"merlin", "foo/bar", "cmd", nil}, | 108 » » {"validCtx", "foo/bar", "anything", nil}, |
109 } { | 109 } { |
110 _, err := s.Call(c, req) | 110 _, err := s.Call(c, req) |
111 c.Assert(err, ErrorMatches, "bad request: Dir is not absolute") | 111 c.Assert(err, ErrorMatches, "bad request: Dir is not absolute") |
112 } | 112 } |
113 } | 113 } |
114 | 114 |
115 func (s *ServerSuite) TestBadContextId(c *C) { | 115 func (s *ServerSuite) TestBadContextId(c *C) { |
116 » _, err := s.Call(c, server.Request{"mordred", c.MkDir(), "magic", nil}) | 116 » _, err := s.Call(c, server.Request{"whatever", c.MkDir(), "remote", nil}
) |
117 » c.Assert(err, ErrorMatches, "bad request: unknown client") | 117 » c.Assert(err, ErrorMatches, `bad request: unknown context "whatever"`) |
118 } | 118 } |
119 | 119 |
120 func (s *ServerSuite) AssertBadCommand(c *C, args []string, code int) server.Res
ponse { | 120 func (s *ServerSuite) AssertBadCommand(c *C, args []string, code int) server.Res
ponse { |
121 » resp, err := s.Call(c, server.Request{"merlin", c.MkDir(), args[0], args
[1:]}) | 121 » resp, err := s.Call(c, server.Request{"validCtx", c.MkDir(), args[0], ar
gs[1:]}) |
122 c.Assert(err, IsNil) | 122 c.Assert(err, IsNil) |
123 c.Assert(resp.Code, Equals, code) | 123 c.Assert(resp.Code, Equals, code) |
124 return resp | 124 return resp |
125 } | 125 } |
126 | 126 |
127 func lines(b []byte) []string { | |
128 return strings.Split(string(b), "\n") | |
129 } | |
130 | |
131 func (s *ServerSuite) TestParseError(c *C) { | 127 func (s *ServerSuite) TestParseError(c *C) { |
132 » resp := s.AssertBadCommand(c, []string{"magic", "--cheese"}, 2) | 128 » resp := s.AssertBadCommand(c, []string{"remote", "--cheese"}, 2) |
133 c.Assert(string(resp.Stdout), Equals, "") | 129 c.Assert(string(resp.Stdout), Equals, "") |
134 » c.Assert(string(resp.Stderr), Equals, `usage: magic [options] | 130 » c.Assert(string(resp.Stderr), Equals, `usage: remote [options] |
135 purpose: do magic | 131 purpose: act at a distance |
136 | 132 |
137 options: | 133 options: |
138 --value (= "") | 134 --value (= "") |
139 doc | 135 doc |
140 | 136 |
141 blah doc | 137 blah doc |
142 error: flag provided but not defined: --cheese | 138 error: flag provided but not defined: --cheese |
143 `) | 139 `) |
144 } | 140 } |
145 | 141 |
146 func (s *ServerSuite) TestBrokenCommand(c *C) { | 142 func (s *ServerSuite) TestBrokenCommand(c *C) { |
147 » resp := s.AssertBadCommand(c, []string{"magic"}, 1) | 143 » resp := s.AssertBadCommand(c, []string{"remote", "--value", "error"}, 1) |
148 c.Assert(string(resp.Stdout), Equals, "") | 144 c.Assert(string(resp.Stdout), Equals, "") |
149 » c.Assert(string(resp.Stderr), Equals, "error: insufficiently magic\n") | 145 » c.Assert(string(resp.Stderr), Equals, "error: blam\n") |
150 } | 146 } |
LEFT | RIGHT |