Blob


1 package p9p
3 import (
4 "bytes"
5 "errors"
6 "reflect"
7 "testing"
8 "time"
9 )
11 func TestEncodeDecode(t *testing.T) {
12 codec := NewCodec()
13 for _, testcase := range []struct {
14 description string
15 target interface{}
16 marshaled []byte
17 }{
18 {
19 description: "uint8",
20 target: uint8('U'),
21 marshaled: []byte{0x55},
22 },
23 {
24 description: "uint16",
25 target: uint16(0x5544),
26 marshaled: []byte{0x44, 0x55},
27 },
28 {
29 description: "string",
30 target: "asdf",
31 marshaled: []byte{0x4, 0x0, 0x61, 0x73, 0x64, 0x66},
32 },
33 {
34 description: "[]string",
35 target: []string{"asdf", "qwer", "zxcv"},
36 marshaled: []byte{
37 0x3, 0x0, // len(target)
38 0x4, 0x0, 0x61, 0x73, 0x64, 0x66,
39 0x4, 0x0, 0x71, 0x77, 0x65, 0x72,
40 0x4, 0x0, 0x7a, 0x78, 0x63, 0x76},
41 },
42 {
43 description: "Qid",
44 target: Qid{
45 Type: QTDIR,
46 Version: 0x10203040,
47 Path: 0x1020304050607080},
48 marshaled: []byte{
49 byte(QTDIR), // qtype
50 0x40, 0x30, 0x20, 0x10, // version
51 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, // path
52 },
53 },
54 // Dir
55 {
56 description: "Tversion fcall",
57 target: &Fcall{
58 Type: Tversion,
59 Tag: 2255,
60 Message: MessageTversion{
61 MSize: uint32(1024),
62 Version: "9PTEST",
63 },
64 },
65 marshaled: []byte{
66 0x64, 0xcf, 0x8, 0x0, 0x4, 0x0, 0x0,
67 0x6, 0x0, 0x39, 0x50, 0x54, 0x45, 0x53, 0x54},
68 },
69 {
70 description: "Rversion fcall",
71 target: &Fcall{
72 Type: Rversion,
73 Tag: 2255,
74 Message: MessageRversion{
75 MSize: uint32(1024),
76 Version: "9PTEST",
77 },
78 },
79 marshaled: []byte{
80 0x65, 0xcf, 0x8, 0x0, 0x4, 0x0, 0x0,
81 0x6, 0x0, 0x39, 0x50, 0x54, 0x45, 0x53, 0x54},
82 },
83 {
84 description: "Twalk fcall",
85 target: &Fcall{
86 Type: Twalk,
87 Tag: 5666,
88 Message: MessageTwalk{
89 Fid: 1010,
90 Newfid: 1011,
91 Wnames: []string{"a", "b", "c"},
92 },
93 },
94 marshaled: []byte{
95 0x6e, 0x22, 0x16, 0xf2, 0x3, 0x0, 0x0, 0xf3, 0x3, 0x0, 0x0,
96 0x3, 0x0, // len(wnames)
97 0x1, 0x0, 0x61, // "a"
98 0x1, 0x0, 0x62, // "b"
99 0x1, 0x0, 0x63}, // "c"
100 },
102 description: "Rwalk call",
103 target: &Fcall{
104 Type: Rwalk,
105 Tag: 5556,
106 Message: MessageRwalk{
107 Qids: []Qid{
108 Qid{
109 Type: QTDIR,
110 Path: 1111,
111 Version: 11112,
112 },
113 Qid{Type: QTFILE,
114 Version: 1112,
115 Path: 11114},
116 },
117 },
118 },
119 marshaled: []byte{
120 0x6f, 0xb4, 0x15,
121 0x2, 0x0,
122 0x80, 0x68, 0x2b, 0x0, 0x0, 0x57, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
123 0x0, 0x58, 0x4, 0x0, 0x0, 0x6a, 0x2b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
124 },
126 description: "Rread fcall",
127 target: &Fcall{
128 Type: Rread,
129 Tag: 5556,
130 Message: MessageRread{
131 Data: []byte("a lot of byte data"),
132 },
133 },
134 marshaled: []byte{
135 0x75, 0xb4, 0x15,
136 0x12, 0x0, 0x0, 0x0,
137 0x61, 0x20, 0x6c, 0x6f, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61},
138 },
140 description: "",
141 target: &Fcall{
142 Type: Rstat,
143 Tag: 5556,
144 Message: MessageRstat{
145 Stat: Dir{
146 Type: ^uint16(0),
147 Dev: ^uint32(0),
148 Qid: Qid{
149 Type: QTDIR,
150 Version: ^uint32(0),
151 Path: ^uint64(0),
152 },
153 Mode: DMDIR | DMREAD,
154 AccessTime: time.Date(2006, 01, 02, 03, 04, 05, 0, time.UTC),
155 ModTime: time.Date(2006, 01, 02, 03, 04, 05, 0, time.UTC),
156 Length: ^uint64(0),
157 Name: "somedir",
158 UID: "uid",
159 GID: "gid",
160 MUID: "muid",
161 },
162 },
163 },
164 marshaled: []byte{
165 0x7d, 0xb4, 0x15,
166 0x42, 0x0, // TODO(stevvooe): Include Dir size. Not straightforward.
167 0x40, 0x0, // TODO(stevvooe): Include Dir size. Not straightforward.
168 0xff, 0xff, // type
169 0xff, 0xff, 0xff, 0xff, // dev
170 0x80, 0xff, 0xff, 0xff, 0xff, // qid.type, qid.version
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // qid.path
172 0x4, 0x0, 0x0, 0x80, // mode
173 0x25, 0x98, 0xb8, 0x43, // atime
174 0x25, 0x98, 0xb8, 0x43, // mtime
175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // length
176 0x7, 0x0, 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x69, 0x72,
177 0x3, 0x0, 0x75, 0x69, 0x64, // uid
178 0x3, 0x0, 0x67, 0x69, 0x64, // gid
179 0x4, 0x0, 0x6d, 0x75, 0x69, 0x64}, // muid
180 },
182 description: "Rerror fcall",
183 target: newErrorFcall(5556, errors.New("A serious error")),
184 marshaled: []byte{
185 0x6b, // Rerror
186 0xb4, 0x15, // Tag
187 0xf, 0x0, // String size.
188 0x41, 0x20, 0x73, 0x65, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72},
189 },
190 } {
191 t.Logf("target under test: %#v %T", testcase.target, testcase.target)
192 fatalf := func(format string, args ...interface{}) {
193 t.Fatalf(testcase.description+": "+format, args...)
196 p, err := codec.Marshal(testcase.target)
197 if err != nil {
198 fatalf("error writing fcall: %v", err)
201 if !bytes.Equal(p, testcase.marshaled) {
202 fatalf("unexpected bytes for fcall: \n%#v != \n%#v", p, testcase.marshaled)
205 if size9p(testcase.target) == 0 {
206 fatalf("size of target should never be zero")
209 // check that size9p is working correctly
210 if int(size9p(testcase.target)) != len(testcase.marshaled) {
211 fatalf("size not correct: %v != %v", int(size9p(testcase.target)), len(testcase.marshaled))
214 var v interface{}
215 targetType := reflect.TypeOf(testcase.target)
217 if targetType.Kind() == reflect.Ptr {
218 v = reflect.New(targetType.Elem()).Interface()
219 } else {
220 v = reflect.New(targetType).Interface()
223 if err := codec.Unmarshal(p, v); err != nil {
224 fatalf("error reading: %v", err)
227 if targetType.Kind() != reflect.Ptr {
228 v = reflect.Indirect(reflect.ValueOf(v)).Interface()
231 if !reflect.DeepEqual(v, testcase.target) {
232 fatalf("not equal: %v != %v (\n%#v\n%#v\n)",
233 v, testcase.target,
234 v, testcase.target)
237 t.Logf("%#v", v)