Blob


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